FINERACT-2009: Upgrade latest framework libs

This commit is contained in:
Aleksandar Vidakovic
2024-01-06 14:13:33 +01:00
committed by Aleksandar Vidakovic
parent 1f3bb34e13
commit e4944c44d6
193 changed files with 1567 additions and 1390 deletions
+6 -4
View File
@@ -16,17 +16,19 @@ jobs:
with:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4
with:
java-version: '17'
distribution: 'zulu'
cache: gradle
- name: Build the image
run: ./gradlew :fineract-provider:clean :fineract-provider:jibDockerBuild -x test
run: ./gradlew --no-daemon --console=plain :fineract-provider:clean :fineract-provider:build :fineract-provider:jibDockerBuild -x test -x cucumber
- name: Start the stack
run: docker-compose up -d
run: docker compose up -d
- name: Wait for stack to come up
run: sleep 300
run: sleep 500
- name: Check the stack
run: docker ps
- name: Check health
run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
- name: Check info
@@ -16,17 +16,19 @@ jobs:
with:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4
with:
java-version: '17'
distribution: 'zulu'
cache: gradle
- name: Build the image
run: ./gradlew --no-daemon --console=plain :fineract-provider:clean :fineract-provider:jibDockerBuild -x test
run: ./gradlew --no-daemon --console=plain :fineract-provider:clean :fineract-provider:build :fineract-provider:jibDockerBuild -x test -x cucumber
- name: Start the Standalone Stack
run: docker-compose -f docker-compose-postgresql.yml up -d
run: docker compose -f docker-compose-postgresql.yml up -d
- name: Wait for stack to come up
run: sleep 300
run: sleep 500
- name: Check the stack
run: docker ps
- name: Check health
run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
- name: Check info
+2 -2
View File
@@ -15,12 +15,12 @@ jobs:
with:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4
with:
java-version: '17'
distribution: 'zulu'
cache: gradle
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4
- uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4
with:
node-version: 16
- name: Congfigure vega-cli
+7 -6
View File
@@ -10,7 +10,7 @@ jobs:
services:
mariad:
image: mariadb:11.1
image: mariadb:11.2
ports:
- 3306:3306
env:
@@ -18,7 +18,7 @@ jobs:
options: --health-cmd="healthcheck.sh --su-mysql --connect --innodb_initialized" --health-interval=5s --health-timeout=2s --health-retries=3
mock-oauth2-server:
image: ghcr.io/navikt/mock-oauth2-server:2.0.1
image: ghcr.io/navikt/mock-oauth2-server:2.1.0
ports:
- 9000:9000
env:
@@ -34,12 +34,12 @@ jobs:
with:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4
with:
java-version: '17'
distribution: 'zulu'
cache: gradle
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4
- uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4
with:
node-version: 16
- name: Congfigure vega-cli
@@ -88,17 +88,18 @@ jobs:
- name: Archive test results
if: always()
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # tag=v3
uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # tag=v3
with:
name: test-results
path: |
build/reports/
integration-tests/build/reports/
twofactor-tests/build/reports/
oauth2-tests/build/reports/
- name: Archive server logs
if: always()
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # tag=v3
uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # tag=v3
with:
name: server-logs
path: |
+6 -5
View File
@@ -18,7 +18,7 @@ jobs:
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
mock-oauth2-server:
image: ghcr.io/navikt/mock-oauth2-server:2.0.1
image: ghcr.io/navikt/mock-oauth2-server:2.1.0
ports:
- 9000:9000
env:
@@ -34,12 +34,12 @@ jobs:
with:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4
with:
java-version: '17'
distribution: 'zulu'
cache: gradle
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4
- uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4
with:
node-version: 16
- name: Congfigure vega-cli
@@ -88,17 +88,18 @@ jobs:
- name: Archive test results
if: always()
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # tag=v3
uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # tag=v3
with:
name: test-results
path: |
build/reports/
integration-tests/build/reports/
twofactor-tests/build/reports/
oauth2-tests/build/reports/
- name: Archive server logs
if: always()
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # tag=v3
uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # tag=v3
with:
name: server-logs
path: |
+6 -5
View File
@@ -19,7 +19,7 @@ jobs:
options: --health-cmd="pg_isready -q -d postgres -U root" --health-interval=5s --health-timeout=2s --health-retries=3
mock-oauth2-server:
image: ghcr.io/navikt/mock-oauth2-server:2.0.1
image: ghcr.io/navikt/mock-oauth2-server:2.1.0
ports:
- 9000:9000
env:
@@ -35,12 +35,12 @@ jobs:
with:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4
with:
java-version: '17'
distribution: 'zulu'
cache: gradle
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4
- uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4
with:
node-version: 16
- name: Congfigure vega-cli
@@ -89,17 +89,18 @@ jobs:
- name: Archive test results
if: always()
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # tag=v3
uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # tag=v3
with:
name: test-results
path: |
build/reports/
integration-tests/build/reports/
twofactor-tests/build/reports/
oauth2-tests/build/reports/
- name: Archive server logs
if: always()
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # tag=v3
uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # tag=v3
with:
name: server-logs
path: |
+5 -3
View File
@@ -16,17 +16,19 @@ jobs:
with:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4
with:
java-version: '17'
distribution: 'zulu'
cache: gradle
- name: Build the image
run: ./gradlew --no-daemon --console=plain :fineract-provider:clean :fineract-provider:jibDockerBuild -x test
run: ./gradlew --no-daemon --console=plain :fineract-provider:clean :fineract-provider:build :fineract-provider:jibDockerBuild -x test -x cucumber
- name: Start the ActiveMQ Stack
run: docker-compose -f docker-compose-postgresql-activemq.yml up --scale fineract-worker=1 -d
run: docker compose -f docker-compose-postgresql-activemq.yml up --scale fineract-worker=1 -d
- name: Wait for stack to come up
run: sleep 500
- name: Check the stack
run: docker ps
- name: Check health Manager
run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
- name: Check health Worker1
+5 -3
View File
@@ -16,17 +16,19 @@ jobs:
with:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4
with:
java-version: '17'
distribution: 'zulu'
cache: gradle
- name: Build the image
run: ./gradlew --no-daemon --console=plain :fineract-provider:clean :fineract-provider:jibDockerBuild -x test
run: ./gradlew --no-daemon --console=plain :fineract-provider:clean :fineract-provider:build :fineract-provider:jibDockerBuild -x test -x cucumber
- name: Start the Kafka Stack
run: docker-compose -f docker-compose-postgresql-kafka.yml up --scale fineract-worker=1 -d
run: docker compose -f docker-compose-postgresql-kafka.yml up --scale fineract-worker=1 -d
- name: Wait for stack to come up
run: sleep 500
- name: Check the stack
run: docker ps
- name: Check health Manager
run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
- name: Check health Worker1
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
with:
fetch-depth: 0
- name: Set up JDK 17
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4
with:
java-version: '17'
distribution: 'zulu'
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
pull-requests: write # for actions/stale to close stale PRs
runs-on: ubuntu-latest
steps:
- uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8
- uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
# stale-issue-message: 'Stale issue message'
+64
View File
@@ -0,0 +1,64 @@
{
"jfrConfig": {
"settings": "profile"
},
"asyncProfilerConfig": {
"jfrsync": true,
"alloc": true,
"event": "wall",
"misc": ""
},
"file": "$PROJECT_DIR/profile.jfr",
"conversionConfig": {
"nonProjectPackagePrefixes": [
"java.",
"javax.",
"kotlin.",
"jdk.",
"com.google.",
"org.apache.",
"org.spring.",
"sun.",
"scala."
],
"enableMarkers": true,
"initialVisibleThreads": 10,
"initialSelectedThreads": 10,
"includeGCThreads": false,
"includeInitialSystemProperty": false,
"includeInitialEnvironmentVariables": false,
"includeSystemProcesses": false,
"ignoredEvents": [
"jdk.ActiveSetting",
"jdk.ActiveRecording",
"jdk.BooleanFlag",
"jdk.IntFlag",
"jdk.DoubleFlag",
"jdk.LongFlag",
"jdk.NativeLibrary",
"jdk.StringFlag",
"jdk.UnsignedIntFlag",
"jdk.UnsignedLongFlag",
"jdk.InitialSystemProperty",
"jdk.InitialEnvironmentVariable",
"jdk.SystemProcess",
"jdk.ModuleExport",
"jdk.ModuleRequire"
],
"minRequiredItemsPerThread": 3
},
"additionalGradleTargets": [
{
"targetPrefix": "quarkus",
"optionForVmArgs": "-Djvm.args",
"description": "Example quarkus config, adding profiling arguments via -Djvm.args option to the Gradle task run"
}
],
"additionalMavenTargets": [
{
"targetPrefix": "quarkus:",
"optionForVmArgs": "-Djvm.args",
"description": "Example quarkus config, adding profiling arguments via -Djvm.args option to the Maven goal run"
}
]
}
+15 -12
View File
@@ -1,6 +1,6 @@
Apache Fineract: A Platform for Microfinance
============
[![Swagger Validation](https://validator.swagger.io/validator?url=https://demo.fineract.dev/fineract-provider/swagger-ui/fineract.yaml)](https://validator.swagger.io/validator/debug?url=https://demo.fineract.dev/fineract-provider/swagger-ui/fineract.yaml) [![build](https://github.com/apache/fineract/actions/workflows/build.yml/badge.svg)](https://github.com/apache/fineract/actions/workflows/build.yml) [![Docker Hub](https://img.shields.io/docker/pulls/apache/fineract.svg?logo=Docker)](https://hub.docker.com/r/apache/fineract) [![Docker Build](https://img.shields.io/docker/cloud/build/apache/fineract.svg?logo=Docker)](https://hub.docker.com/r/apache/fineract/builds) [![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=apache_fineract&metric=sqale_index)](https://sonarcloud.io/summary/new_code?id=apache_fineract)
[![Swagger Validation](https://validator.swagger.io/validator?url=https://sandbox.mifos.community/fineract-provider/swagger-ui/fineract.yaml)](https://validator.swagger.io/validator/debug?url=https://sandbox.mifos.community/fineract-provider/swagger-ui/fineract.yaml) [![build](https://github.com/apache/fineract/actions/workflows/build.yml/badge.svg)](https://github.com/apache/fineract/actions/workflows/build.yml) [![Docker Hub](https://img.shields.io/docker/pulls/apache/fineract.svg?logo=Docker)](https://hub.docker.com/r/apache/fineract) [![Docker Build](https://img.shields.io/docker/cloud/build/apache/fineract.svg?logo=Docker)](https://hub.docker.com/r/apache/fineract/builds) [![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=apache_fineract&metric=sqale_index)](https://sonarcloud.io/summary/new_code?id=apache_fineract)
</b>
@@ -22,15 +22,15 @@ If you are interested in contributing to this project, but perhaps don't quite k
REQUIREMENTS
============
* `Java >= 17` (Azul Zulu JVM is tested by our CI on GitHub Actions)
* MariaDB `10.9`
* MariaDB `11.2`
You can run the required version of the database server in a container, instead of having to install it, like this:
docker run --name mariadb-10.9 -p 3306:3306 -e MARIADB_ROOT_PASSWORD=mysql -d mariadb:10.9
docker run --name mariadb-11.2 -p 3306:3306 -e MARIADB_ROOT_PASSWORD=mysql -d mariadb:11.2
and stop and destroy it like this:
docker rm -f mariadb-10.9
docker rm -f mariadb-11.2
<br>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](https://hub.docker.com/_/mariadb) re. how to make it persistent instead of ephemeral.<br>
@@ -75,7 +75,7 @@ Run the following commands:
============
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 `fineract-provider/build/libs` directory.
3. As we are not allowed to include a JDBC driver in the built JAR, download a JDBC driver of your choice. For example: `wget https://downloads.mariadb.com/Connectors/java/connector-java-2.7.5/mariadb-java-client-2.7.5.jar`
3. As we are not allowed to include a JDBC driver in the built JAR, download a JDBC driver of your choice. For example: `wget https://downloads.mariadb.com/Connectors/java/connector-java-3.3.2/mariadb-java-client-3.3.2.jar`
4. Start the jar and pass the directory where you have downloaded the JDBC driver as loader.path, for example: `java -Dloader.path=. -jar fineract-provider/build/libs/fineract-provider.jar` (does not require external Tomcat)
NOTE: we cannot upgrade to version 3.0.x of the MariaDB driver just yet; have to wait until 3.0.4 is out for a bug fix.
@@ -207,13 +207,16 @@ _(Note that in previous versions, the `mysqlserver` environment variable used at
`docker run` time did something similar; this has changed in [FINERACT-773](https://issues.apache.org/jira/browse/FINERACT-773)),
and the `mysqlserver` environment variable is now no longer supported.)_
If you need the Java Flight Recorder image then copy the file from the running fineract-development container:
The logfiles and the Java Flight Recorder output are available in `PROJECT_ROOT/build/fineract/logs`. If you use IntelliJ then you can double-click on the `.jfr` file and open it with the IDE. You can also download Azul Mission Control from here https://www.azul.com/products/components/azul-mission-control/ to analyze the Java Flight Recorder file.
NOTE: If you have issues with the file permissions and Docker Compose then you might need to change the variable values for `FINERACT_USER` and `FINERACT_GROUP` in `PROJECT_ROOT/config/docker/env/fineract-common.env`. You can find out what values you need to put there with the following commands:
```
docker container cp fineract-development:/tmp/fineract.jfr /tmp
id -u ${USER}
id -u ${GROUP}
```
NOTE: Download Azul Mission Control from here https://www.azul.com/products/components/azul-mission-control/ to analyze the Java Flight Recorder file.
Please make sure that you are not checking in your changed values. The defaults should normally work for most people.
Connection pool configuration
=============================
@@ -399,9 +402,9 @@ complies with the [Apache Software Foundation third-party license policy](https:
<br><br>APACHE FINERACT PLATFORM API
============
The API for Fineract is documented in [apiLive.htm](fineract-provider/src/main/resources/static/api-docs/apiLive.htm), and the [apiLive.htm can be viewed on Fineract.dev](https://fineract.apache.org/legacy-docs/apiLive.htm "API Documentation"). If you have your own Fineract instance running, you can find this documentation under [/fineract-provider/api-docs/apiLive.htm](https://localhost:8443/fineract-provider/api-docs/apiLive.htm).
The API for Fineract is documented in [apiLive.htm](fineract-provider/src/main/resources/static/legacy-docs/apiLive.htm), and the [apiLive.htm can be viewed on fineract.apache.org](https://fineract.apache.org/docs/legacy/ "API Documentation"). If you have your own Fineract instance running, you can find this documentation under [/fineract-provider/legacy-docs/apiLive.htm](https://localhost:8443/fineract-provider/legacy-docs/apiLive.htm).
The Swagger documentation (work in progress; see [FINERACT-733](https://issues.apache.org/jira/browse/FINERACT-733)) can be accessed under [/fineract-provider/swagger-ui/index.html](https://localhost:8443/fineract-provider/swagger-ui/index.html) and [live Swagger UI here on Fineract.dev](https://demo.fineract.dev/fineract-provider/swagger-ui/index.html).
The Swagger documentation (work in progress; see [FINERACT-733](https://issues.apache.org/jira/browse/FINERACT-733)) can be accessed under [/fineract-provider/swagger-ui/index.html](https://localhost:8443/fineract-provider/swagger-ui/index.html) and [live Swagger UI here on Fineract.dev](https://sandbox.mifos.community/fineract-provider/swagger-ui/index.html).
Apache Fineract supports client code generation using [Swagger Codegen](https://github.com/swagger-api/swagger-codegen) based on the [OpenAPI Specification](https://swagger.io/specification/). For more instructions on how to generate the client code, check [docs/developers/swagger/client.md](docs/developers/swagger/client.md).
@@ -418,7 +421,7 @@ Apache Fineract supports client code generation using [Swagger Codegen](https://
<br>ONLINE DEMOS
============
* [fineract.dev](https://www.fineract.dev) always runs the latest version of this code
* [sandbox.mifos.community](https://sandbox.mifos.community) always runs the latest version of this code
* [demo.mifos.io](https://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](https://www.youtube.com/watch?v=FlVd-0YAo6c) This is a demo video for Swagger-UI documentation, more information [here](https://github.com/apache/fineract#swagger-ui-documentation).
@@ -443,7 +446,7 @@ Apache Fineract / Mifos X Demo (November 2016) - <https://www.youtube.com/watch?
============
We use Swagger-UI to generate and maintain our API documentation, you can see the demo video [here](https://www.youtube.com/watch?v=FlVd-0YAo6c) or a live version
[here](https://demo.fineract.dev/fineract-provider/swagger-ui/index.html). If you interested to know more about Swagger-UI you can check their [website](https://swagger.io/).
[here](https://sandbox.mifos.community/fineract-provider/swagger-ui/index.html). If you interested to know more about Swagger-UI you can check their [website](https://swagger.io/).
<br>GORVENANCE AND POLICIES
=======================
+22 -10
View File
@@ -61,7 +61,7 @@ buildscript {
classpath 'jakarta.ws.rs:jakarta.ws.rs-api:3.1.0'
classpath 'com.google.cloud.tools:jib-layer-filter-extension-gradle:0.3.0'
classpath 'org.apache.commons:commons-lang3:3.14.0'
classpath 'io.swagger.core.v3:swagger-jaxrs2-jakarta:2.2.11'
classpath 'io.swagger.core.v3:swagger-jaxrs2-jakarta:2.2.19'
classpath 'jakarta.servlet:jakarta.servlet-api:6.0.0'
}
}
@@ -70,14 +70,14 @@ plugins {
id 'me.qoomon.git-versioning' version '6.4.3'
id "org.barfuin.gradle.taskinfo" version "2.1.0"
id 'com.adarshr.test-logger' version '4.0.0'
id 'com.diffplug.spotless' version '6.22.0' apply false
id 'com.diffplug.spotless' version '6.23.3' apply false
id 'org.nosphere.apache.rat' version '0.8.1' apply false
id 'com.github.hierynomus.license' version '0.16.1' apply false
id 'com.github.jk1.dependency-license-report' version '2.5' apply false
id 'org.zeroturnaround.gradle.jrebel' version '1.2.0' apply false
id 'org.springframework.boot' version '3.1.5' apply false
id 'org.springframework.boot' version '3.1.7' apply false
id 'net.ltgt.errorprone' version '3.1.0' apply false
id 'io.swagger.core.v3.swagger-gradle-plugin' version '2.2.11' apply false
id 'io.swagger.core.v3.swagger-gradle-plugin' version '2.2.19' apply false
id 'com.gorylenko.gradle-git-properties' version '2.4.1' apply false
id 'org.asciidoctor.jvm.convert' version '3.3.2' apply false
id 'org.asciidoctor.jvm.pdf' version '3.3.2' apply false
@@ -88,9 +88,11 @@ plugins {
id 'com.google.cloud.tools.jib' version '3.4.0' apply false
id 'org.sonarqube' version '4.4.1.3373'
id 'com.github.andygoossens.modernizer' version '1.9.0' apply false
id 'com.github.spotbugs' version '5.0.14' apply false
// TODO: upgrade to 6.0.4
id 'com.github.spotbugs' version '5.0.15' apply false
id 'se.thinkcode.cucumber-runner' version '0.0.11' apply false
id "com.github.davidmc24.gradle.plugin.avro-base" version "1.9.1" apply false
id 'org.openapi.generator' version '7.2.0' apply false
}
apply from: "${rootDir}/buildSrc/src/main/groovy/org.apache.fineract.release.gradle"
@@ -119,7 +121,7 @@ gitVersioning.apply {
}
}
ext['groovy.version'] = '4.0.6'
ext['groovy.version'] = '4.0.17'
ext['swaggerFile'] = "$rootDir/fineract-provider/build/classes/java/main/static/fineract.json".toString()
allprojects {
@@ -143,7 +145,7 @@ allprojects {
spotless {
format 'misc', {
target '**/*.md', '**/*.properties', '**/.gitignore', '**/.openapi-generator-ignore', '**/*.yml', '**/*.xml', '**/**.json', '**/*.sql'
targetExclude '**/build/**', '**/bin/**', '**/.settings/**', '**/.idea/**', '**/.gradle/**', '**/gradlew.bat', '**/licenses/**', '**/banner.txt', '.vscode/**'
targetExclude '**/build/**', '**/bin/**', '**/.settings/**', '**/.idea/**', '**/.gradle/**', '**/gradlew.bat', '**/licenses/**', '**/banner.txt', '.vscode/**', '.profileconfig.json'
indentWithSpaces(4)
endWithNewline()
trimTrailingWhitespace()
@@ -321,6 +323,15 @@ configure(project.fineractJavaProjects) {
sourceSets.main.output.resourcesDir = sourceSets.main.java.classesDirectory
sourceSets.test.output.resourcesDir = sourceSets.test.java.classesDirectory
configurations.named('spotbugs').configure {
resolutionStrategy.eachDependency {
if (it.requested.group == 'org.ow2.asm') {
it.useVersion '9.5'
it.because "Asm 9.5 is required for JDK 21 support"
}
}
}
configurations {
implementation.setCanBeResolved(true)
api.setCanBeResolved(true)
@@ -423,7 +434,7 @@ configure(project.fineractJavaProjects) {
// Configuration for the Checkstyle plugin
// https://docs.gradle.org/current/userguide/checkstyle_plugin.html
dependencies {
checkstyle 'com.puppycrawl.tools:checkstyle:10.12.5'
checkstyle 'com.puppycrawl.tools:checkstyle:10.12.7'
checkstyle 'com.github.sevntu-checkstyle:sevntu-checks:1.44.1'
}
@@ -445,7 +456,7 @@ configure(project.fineractJavaProjects) {
// Configuration for the errorprone plugin
// https://github.com/tbroyer/gradle-errorprone-plugin
dependencies {
errorprone "com.google.errorprone:error_prone_core:2.23.0"
errorprone "com.google.errorprone:error_prone_core:2.24.0"
}
tasks.withType(JavaCompile) {
@@ -600,7 +611,8 @@ configure(project.fineractJavaProjects) {
// To generate an HTML report instead of XML
spotbugs {
reportLevel = 'high'
// reportLevel = 'high'
// reportLevel = com.github.spotbugs.snom.Confidence.DEFAULT
showProgress = false
excludeFilter = file("$rootDir/config/spotbugs/exclude.xml")
}
+1
View File
@@ -58,4 +58,5 @@ dependencies {
implementation 'com.squareup.retrofit2:retrofit'
implementation 'com.squareup.retrofit2:converter-jackson'
implementation 'com.fasterxml.jackson.core:jackson-databind'
implementation 'com.squareup.okhttp3:okhttp'
}
@@ -22,18 +22,21 @@ apply plugin: 'io.spring.dependency-management'
// https://github.com/spring-gradle-plugins/dependency-management-plugin
dependencyManagement {
imports {
mavenBom 'io.micrometer:micrometer-bom:1.12.0'
mavenBom 'org.springframework:spring-framework-bom:6.1.0'
mavenBom 'org.springframework.boot:spring-boot-dependencies:3.1.5'
mavenBom 'io.awspring.cloud:spring-cloud-aws-dependencies:3.0.3'
mavenBom 'io.opentelemetry:opentelemetry-bom:1.32.0'
mavenBom 'org.jetbrains.kotlin:kotlin-bom:1.9.20'
mavenBom 'com.squareup.okhttp3:okhttp-bom:4.12.0'
mavenBom 'org.slf4j:slf4j-bom:2.0.10'
mavenBom 'io.micrometer:micrometer-bom:1.12.1'
mavenBom 'org.springframework:spring-framework-bom:6.1.2'
mavenBom 'org.springframework.boot:spring-boot-dependencies:3.1.7'
mavenBom 'io.awspring.cloud:spring-cloud-aws-dependencies:3.0.4'
mavenBom 'io.opentelemetry:opentelemetry-bom:1.33.0'
mavenBom 'org.jetbrains.kotlin:kotlin-bom:1.9.22'
mavenBom 'org.junit:junit-bom:5.10.1'
mavenBom 'com.fasterxml.jackson:jackson-bom:2.16.0'
mavenBom 'io.cucumber:cucumber-bom:7.14.0'
mavenBom 'io.netty:netty-bom:4.1.101.Final'
mavenBom 'org.mockito:mockito-bom:5.7.0'
mavenBom 'software.amazon.awssdk:bom:2.21.28'
mavenBom 'com.fasterxml.jackson:jackson-bom:2.16.1'
mavenBom 'io.cucumber:cucumber-bom:7.15.0'
mavenBom 'io.netty:netty-bom:4.1.104.Final'
mavenBom 'org.mockito:mockito-bom:5.8.0'
mavenBom 'software.amazon.awssdk:bom:2.22.9'
mavenBom 'io.github.resilience4j:resilience4j-bom:2.2.0'
}
dependencies {
@@ -41,37 +44,31 @@ dependencyManagement {
// We do not use :+ to get the latest available version available on Maven Central, as that could suddenly break things.
// We use the Renovate Bot to automatically propose Pull Requests (PRs) when upgrades for all of these versions are available.
dependency 'org.slf4j:slf4j-api:2.0.9'
dependency 'org.slf4j:slf4j-simple:2.0.9'
dependency 'org.slf4j:jcl-over-slf4j:2.0.9'
dependency 'org.slf4j:jul-to-slf4j:2.0.9'
dependency 'org.slf4j:log4j-over-slf4j:2.0.9'
dependency 'ch.qos.logback:logback-core:1.4.11'
dependency 'ch.qos.logback:logback-classic:1.4.11'
dependency 'ch.qos.logback:logback-core:1.4.14'
dependency 'ch.qos.logback:logback-classic:1.4.14'
dependency 'ch.qos.logback.contrib:logback-json-classic:0.1.5'
dependency 'ch.qos.logback.contrib:logback-jackson:0.1.5'
dependency 'org.codehaus.janino:janino:3.1.10'
dependency 'org.codehaus.janino:janino:3.1.11'
dependency 'org.eclipse.persistence:org.eclipse.persistence.jpa:4.0.0'
dependency 'com.google.guava:guava:32.0.0-jre'
dependency 'com.google.code.gson:gson:2.10.1'
dependency 'com.google.truth:truth:1.1.5'
dependency 'com.google.truth.extensions:truth-java8-extension:1.1.5'
dependency 'com.google.googlejavaformat:google-java-format:1.18.1'
dependency ('org.apache.commons:commons-email:1.5') {
dependency 'com.google.truth:truth:1.2.0'
dependency 'com.google.truth.extensions:truth-java8-extension:1.2.0'
dependency 'com.google.googlejavaformat:google-java-format:1.19.1'
dependency ('org.apache.commons:commons-email:1.6.0') {
exclude 'com.sun.mail:javax.mail'
exclude 'javax.activation:activation'
}
dependency 'commons-io:commons-io:2.15.0'
dependency 'com.github.librepdf:openpdf:1.3.33'
dependency 'commons-io:commons-io:2.15.1'
dependency 'com.github.librepdf:openpdf:1.3.35'
dependency ('org.mnode.ical4j:ical4j:3.2.14') {
exclude 'com.sun.mail:javax.mail'
exclude 'org.codehaus.groovy:groovy'
}
dependency 'org.apache.commons:commons-csv:1.10.0'
dependency 'org.quartz-scheduler:quartz:2.3.2'
dependency 'software.amazon.awssdk:bom:2.21.28'
dependency 'org.ehcache:ehcache:3.10.8'
dependency 'com.github.spullara.mustache.java:compiler:0.9.11'
dependency 'com.jayway.jsonpath:json-path:2.8.0'
@@ -119,13 +116,14 @@ dependencyManagement {
dependency 'jakarta.management.j2ee:jakarta.management.j2ee-api:1.1.4'
dependency 'jakarta.jms:jakarta.jms-api:3.1.0'
dependency 'jakarta.ws.rs:jakarta.ws.rs-api:3.1.0'
dependency 'org.glassfish.jersey.media:jersey-media-multipart:3.1.3'
dependency 'org.glassfish.jersey.media:jersey-media-multipart:3.1.5'
dependency 'org.glassfish.jaxb:jaxb-runtime:2.3.6' // Swagger needs exactly this version
dependency 'org.apache.bval:org.apache.bval.bundle:3.0.0'
dependency 'joda-time:joda-time:2.12.5'
dependency 'io.github.classgraph:classgraph:4.8.165'
dependency 'org.awaitility:awaitility:4.2.0'
// TODO: upgrade to 4.8.3
dependency 'com.github.spotbugs:spotbugs-annotations:4.7.3'
dependency 'javax.cache:cache-api:1.1.1'
dependency 'org.mock-server:mockserver-junit-jupiter:5.15.0'
@@ -148,16 +146,10 @@ dependencyManagement {
dependency "com.squareup.retrofit2:converter-scalars:2.9.0"
dependency "com.squareup.retrofit2:converter-gson:2.9.0"
dependency "com.squareup.retrofit2:converter-protobuf:2.9.0"
dependency 'io.reactivex.rxjava2:rxjava:2.2.21'
dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.common:1.0.1"
dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:1.0.1"
dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.httpclient4:1.0.1"
dependency "com.squareup.okhttp3:okhttp:4.12.0"
dependency "com.squareup.okhttp3:okcurl:4.12.0"
dependency "com.squareup.okhttp3:logging-interceptor:4.12.0"
dependency "com.squareup.okhttp3:okhttp-apache:4.9.3"
dependency "com.squareup.okhttp3:okhttp-android-support:4.9.3"
dependency "com.squareup.okhttp3:okhttp-urlconnection:4.12.0"
dependency "com.squareup.okhttp3:okhttp-sse:4.12.0"
dependency "io.gsonfire:gson-fire:1.9.0"
dependency "com.google.code.findbugs:jsr305:3.0.2"
dependency "commons-codec:commons-codec:1.16.0"
@@ -168,44 +160,45 @@ dependencyManagement {
dependency 'org.bouncycastle:bcprov-jdk15on:1.70'
dependency 'org.bouncycastle:bcpg-jdk15on:1.70'
dependency 'org.eclipse.jgit:org.eclipse.jgit:6.7.0.202309050840-r'
dependency 'org.eclipse.jgit:org.eclipse.jgit.ssh.apache:6.7.0.202309050840-r'
dependency 'org.eclipse.jgit:org.eclipse.jgit:6.8.0.202311291450-r'
dependency 'org.eclipse.jgit:org.eclipse.jgit.ssh.apache:6.8.0.202311291450-r'
dependency 'org.tmatesoft.svnkit:svnkit:1.10.11'
dependency 'com.vdurmont:semver4j:3.1.0'
dependency 'org.beryx:text-io:3.4.1'
dependency ('org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0') {
dependency ('org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0') {
exclude 'io.swagger.core.v3:swagger-core'
}
dependency 'com.google.cloud.sql:mysql-socket-factory-connector-j-8:1.15.0'
dependency 'com.google.cloud.sql:mysql-socket-factory-connector-j-8:1.15.1'
dependency ('org.apache.activemq:activemq-client:6.0.0') {
dependency ('org.apache.activemq:activemq-client:6.0.1') {
exclude 'javax.annotation:javax.annotation-api'
}
dependency 'io.swagger.core.v3:swagger-annotations-jakarta:2.2.11'
dependency ('io.swagger.core.v3:swagger-jaxrs2-jakarta:2.2.11') {
dependency 'io.swagger.core.v3:swagger-annotations-jakarta:2.2.19'
dependency ('io.swagger.core.v3:swagger-jaxrs2-jakarta:2.2.19') {
exclude 'jakarta.activation:jakarta.activation-api'
}
dependency ('io.swagger.core.v3:swagger-core-jakarta:2.2.11') {
dependency ('io.swagger.core.v3:swagger-core-jakarta:2.2.19') {
exclude 'jakarta.activation:jakarta.activation-api'
}
dependency "jakarta.annotation:jakarta.annotation-api:2.1.1"
dependency 'jakarta.annotation:jakarta.annotation-api:2.1.1'
dependency 'jakarta.activation:jakarta.activation-api:2.1.2'
dependency ('com.sun.mail:jakarta.mail:2.0.1') {
// Spring needs this version
exclude 'com.sun.activation:jakarta.activation'
}
dependency ('jakarta.xml.bind:jakarta.xml.bind-api:4.0.0') {
dependency ('jakarta.xml.bind:jakarta.xml.bind-api:4.0.1') {
exclude 'jakarta.activation:jakarta.activation-api'
}
dependency ('org.liquibase:liquibase-core:4.23.0') {
dependency ('org.liquibase:liquibase-core:4.25.1') {
exclude 'javax.xml.bind:jaxb-api'
}
dependency 'org.liquibase.ext:liquibase-postgresql:4.25.1'
dependency ('org.dom4j:dom4j:2.1.4') {
exclude 'relaxngDatatype:relaxngDatatype' // already in com.sun.xml.bind:jaxb-osgi:2.3.0.1
@@ -214,38 +207,36 @@ dependencyManagement {
exclude 'pull-parser:pull-parser'
}
dependency 'org.owasp.esapi:esapi:2.5.2.0'
dependency 'org.owasp.esapi:esapi:2.5.3.1'
dependency 'org.awaitility:awaitility:4.2.0'
dependencySet(group: 'org.apache.poi', version: '5.2.4') {
dependencySet(group: 'org.apache.poi', version: '5.2.5') {
entry 'poi'
entry 'poi-ooxml'
entry 'poi-ooxml-schemas'
}
dependencySet(group: 'io.rest-assured', version: '5.3.2') {
dependencySet(group: 'io.rest-assured', version: '5.4.0') {
entry 'rest-assured'
entry 'json-path'
entry 'xml-path'
}
dependency 'org.apache.groovy:groovy-xml:4.0.14'
dependency 'org.apache.groovy:groovy-json:4.0.15'
dependency 'org.apache.groovy:groovy-xml:4.0.17'
dependency 'org.apache.groovy:groovy-json:4.0.17'
dependency 'org.mapstruct:mapstruct:1.5.5.Final'
dependency 'org.mapstruct:mapstruct-processor:1.5.5.Final'
dependency "org.apache.avro:avro:1.11.3"
dependency "io.github.resilience4j:resilience4j-spring-boot2:2.1.0"
dependency ('org.mariadb.jdbc:mariadb-java-client:3.3.0') {
dependency ('org.mariadb.jdbc:mariadb-java-client:3.3.2') {
exclude 'org.slf4j:jcl-over-slf4j'
exclude 'org.slf4j:slf4j-api'
}
dependency 'org.postgresql:postgresql:42.7.0'
dependency 'org.postgresql:postgresql:42.7.1'
dependency 'org.assertj:assertj-core:3.24.2'
dependency 'org.assertj:assertj-core:3.25.0'
dependency 'org.apache.commons:commons-math3:3.6.1'
+2 -2
View File
@@ -22,5 +22,5 @@ services:
activemq:
image: symptoma/activemq:5.18.3
ports:
- 6161:6161
- 61616:61616
- "6161:6161"
- "61616:61616"
+32
View File
@@ -0,0 +1,32 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
version: "3.8"
services:
fineract:
# user: "${FINERACT_USER}:${FINERACT_GROUP}"
image: fineract-custom:latest
volumes:
- ${PWD}/config/docker/logback/logback-override.xml:/app/logback-override.xml
- ${PWD}/config/docker/aws/etc/credentials:/etc/aws/credentials:ro
- ${PWD}/build/fineract/logs:/var/logs/fineract:rw
healthcheck:
test: ["CMD", 'sh', '-c', 'echo -e "Checking for the availability of Fineract server deployment"; while ! nc -z "localhost" 8443; do sleep 1; printf "-"; done; echo -e " >> Fineract server has started";' ]
timeout: 1s
retries: 60
+7 -6
View File
@@ -20,12 +20,13 @@ version: "3.8"
services:
fineract:
# user: "${FINERACT_USER}:${FINERACT_GROUP}"
image: fineract:latest
volumes:
- ../aws/etc/credentials:/etc/aws/credentials
- ${PWD}/config/docker/logback/logback-override.xml:/app/logback-override.xml
- ${PWD}/config/docker/aws/etc/credentials:/etc/aws/credentials:ro
- ${PWD}/build/fineract/logs:/var/logs/fineract:rw
healthcheck:
test: ["CMD", 'sh', '-c', 'echo -e "Checking for the availability of Fineract server deployment"; while ! nc -z "fineract-server" 8443; do sleep 1; printf "-"; done; echo -e " >> Fineract server has started";' ]
timeout: 10s
retries: 10
env_file:
- ../env/fineract-common.env
test: ["CMD", 'sh', '-c', 'echo -e "Checking for the availability of Fineract server deployment"; while ! nc -z "localhost" 8443; do sleep 1; printf "-"; done; echo -e " >> Fineract server has started";' ]
timeout: 1s
retries: 60
+5 -7
View File
@@ -13,20 +13,18 @@
# "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.
#
version: "3.8"
services:
mariadb:
image: mariadb:11.0
container_name: mariadb
image: mariadb:11.2
volumes:
- ../mysql/conf.d/server_collation.cnf:/etc/mysql/conf.d/server_collation.cnf
- ../mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d:Z,ro
- ${PWD}/config/docker/mysql/conf.d/server_collation.cnf:/etc/mysql/conf.d/server_collation.cnf:ro
- ${PWD}/config/docker/mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d:Z,ro
restart: always
env_file:
- ../env/mysql.env
- ${PWD}/config/docker/env/mysql.env
healthcheck:
test: [ "CMD", "healthcheck.sh", "--su-mysql", "--connect", "--innodb_initialized" ]
timeout: 10s
+9 -5
View File
@@ -31,31 +31,35 @@ version: "3.8"
services:
loki:
container_name: loki
image: grafana/loki:2.9.2
command: -config.file=/etc/loki/local-config.yaml
ports:
- "3100:3100"
prometheus:
container_name: prometheus
image: prom/prometheus:v2.47.2
command: '--config.file=/etc/prometheus/prometheus.yml'
ports:
- "9090:9090"
volumes:
- ../prometheus/etc:/etc/prometheus
- ${PWD}/config/docker/prometheus/etc:/etc/prometheus
logging: *default-logging
grafana:
container_name: grafana
image: grafana/grafana-oss:10.2.0
ports:
- "3000:3000"
volumes:
- ../grafana/datasources:/etc/grafana/provisioning/datasources
- ../grafana/etc/dashboards.yml:/etc/grafana/provisioning/dashboards/dashboards.yaml
- ../grafana/dashboards:/var/lib/grafana/dashboards
- ${PWD}/config/docker/grafana/datasources:/etc/grafana/provisioning/datasources
- ${PWD}/config/docker/grafana/etc/dashboards.yml:/etc/grafana/provisioning/dashboards/dashboards.yaml
- ${PWD}/config/docker/grafana/dashboards:/var/lib/grafana/dashboards
logging: *default-logging
tempo:
container_name: tempo
image: grafana/tempo:2.2.4
# command: [ "--target=all", "--storage.trace.backend=local", "--storage.trace.local.path=/tmp/tempo", "--auth.enabled=false" ]
command: [ "-config.file=/etc/tempo.yml" ]
@@ -67,6 +71,6 @@ services:
- "4318:4318" # otlp http
- "9411:9411" # zipkin
volumes:
- ../tempo/etc/tempo.yml:/etc/tempo.yml
- ${PWD}/config/docker/tempo/etc/tempo.yml:/etc/tempo.yml
- /tmp/tempo:/tmp/tempo
logging: *default-logging
+3 -3
View File
@@ -20,12 +20,12 @@ version: "3.8"
services:
postgresql:
image: postgres:16.0
image: postgres:16.1
volumes:
- ../postgresql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d/:Z,ro
- ${PWD}/config/docker/postgresql/docker-entrypoint-initdb.d/01-init.sh:/docker-entrypoint-initdb.d/01-init.sh:Z,ro
restart: always
env_file:
- ../env/postgresql.env
- ${PWD}/config/docker/env/postgresql.env
healthcheck:
test: [ "CMD", "pg_isready", "-q", "-d", "postgres", "-U", "root" ]
timeout: 10s
+2 -1
View File
@@ -18,4 +18,5 @@
#
# see here for more details related to JFR: https://access.redhat.com/documentation/en-us/red_hat_build_of_openjdk/8/html/using_jdk_flight_recorder_with_red_hat_build_of_openjdk/configure-jfr-options
JAVA_TOOL_OPTIONS="-Xmx2G -Xms2G -XX:TieredStopAtLevel=1 -XX:+UseContainerSupport -XX:+UseStringDeduplication -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5000 -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints -XX:StartFlightRecording=delay=20s,duration=60s,disk=true,name=fineract,dumponexit=true,filename=/tmp/fineract.jfr,settings=profile -Xlog:jfr=info"
# JAVA_TOOL_OPTIONS="-Xmx2G -Xms2G -Dlogging.config=/app/logback-override.xml -XX:TieredStopAtLevel=1 -XX:+UseContainerSupport -XX:+UseStringDeduplication -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5000 -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints -XX:StartFlightRecording=delay=20s,duration=60s,disk=true,name=fineract,path-to-gc-roots=true,dumponexit=true,filename=/var/logs/fineract/fineract.jfr,settings=profile -Xlog:jfr=info"
JAVA_TOOL_OPTIONS="-Xmx2G -Xms2G -Dlogging.config=/app/logback-override.xml -XX:TieredStopAtLevel=1 -XX:+UseContainerSupport -XX:+UseStringDeduplication -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5000 -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints -Xlog:jfr=info"
+9
View File
@@ -18,6 +18,8 @@
#
# ... following variables are optional; "application.properties" contains reasonable defaults (same as here)
FINERACT_USER=1000
FINERACT_GROUP=1000
FINERACT_HIKARI_MINIMUM_IDLE=3
FINERACT_HIKARI_MAXIMUM_POOL_SIZE=10
FINERACT_HIKARI_IDLE_TIMEOUT=60000
@@ -25,6 +27,8 @@ FINERACT_HIKARI_CONNECTION_TIMEOUT=20000
FINERACT_HIKARI_TEST_QUERY=SELECT 1
FINERACT_HIKARI_AUTO_COMMIT=true
FINERACT_SERVER_SSL_ENABLED=true
FINERACT_HIKARI_USERNAME=root
FINERACT_HIKARI_PASSWORD=skdcnwauicn2ucnaecasdsajdnizucawencascdca
FINERACT_HIKARI_DS_PROPERTIES_CACHE_PREP_STMTS=true
FINERACT_HIKARI_DS_PROPERTIES_PREP_STMT_CACHE_SIZE=250
FINERACT_HIKARI_DS_PROPERTIES_PREP_STMT_CACHE_SQL_LIMIT=2048
@@ -37,14 +41,19 @@ FINERACT_HIKARI_DS_PROPERTIES_ELIDE_SET_AUTO_COMMITS=true
FINERACT_HIKARI_DS_PROPERTIES_MAINTAIN_TIME_STATS=false
FINERACT_HIKARI_DS_PROPERTIES_LOG_SLOW_QUERIES=true
FINERACT_HIKARI_DS_PROPERTIES_DUMP_QUERIES_IN_EXCEPTION=true
# NOTE: env vars prefixed "FINERACT_DEFAULT_TENANTDB_*" are used to create the default tenant database
FINERACT_DEFAULT_TENANTDB_CONN_PARAMS=
FINERACT_DEFAULT_TENANTDB_TIMEZONE=Asia/Kolkata
FINERACT_DEFAULT_TENANTDB_IDENTIFIER=default
FINERACT_DEFAULT_TENANTDB_NAME=fineract_default
FINERACT_DEFAULT_TENANTDB_DESCRIPTION=Default Demo Tenant
FINERACT_DEFAULT_TENANTDB_HOSTNAME=db
FINERACT_DEFAULT_TENANTDB_PWD=skdcnwauicn2ucnaecasdsajdnizucawencascdca
FINERACT_DEFAULT_MASTER_PASSWORD=fineract
FINERACT_MANAGEMENT_ENDPOINT_WEB_EXPOSURE_INCLUDE=health,info,prometheus
FINERACT_MANAGEMENT_METRICS_TAGS_APPLICATION=fineract
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_SPRING_EVENTS_ENABLED=false
FINERACT_INSECURE_HTTP_CLIENT=true
SPRING_PROFILES_ACTIVE=test,diagnostics
OTEL_SERVICE_NAME=fineract
JAVA_TOOL_OPTIONS="-Xmx1G -XX:TieredStopAtLevel=1 -XX:+UseContainerSupport -XX:+UseStringDeduplication"
-4
View File
@@ -20,10 +20,6 @@
# NOTE: env vars prefixed "FINERACT_HIKARI_*" are used to configure the database connection pool
FINERACT_HIKARI_DRIVER_SOURCE_CLASS_NAME=org.mariadb.jdbc.Driver
FINERACT_HIKARI_JDBC_URL=jdbc:mariadb://db:3306/fineract_tenants
FINERACT_HIKARI_USERNAME=root
FINERACT_HIKARI_PASSWORD=skdcnwauicn2ucnaecasdsajdnizucawencascdca
# NOTE: env vars prefixed "FINERACT_DEFAULT_TENANTDB_*" are used to create the default tenant database
FINERACT_DEFAULT_TENANTDB_HOSTNAME=db
FINERACT_DEFAULT_TENANTDB_PORT=3306
FINERACT_DEFAULT_TENANTDB_UID=root
FINERACT_DEFAULT_TENANTDB_PWD=skdcnwauicn2ucnaecasdsajdnizucawencascdca
-2
View File
@@ -23,7 +23,5 @@ FINERACT_HIKARI_JDBC_URL=jdbc:postgresql://db:5432/fineract_tenants
FINERACT_HIKARI_USERNAME=postgres
FINERACT_HIKARI_PASSWORD=skdcnwauicn2ucnaecasdsajdnizucawencascdca
# NOTE: env vars prefixed "FINERACT_DEFAULT_TENANTDB_*" are used to create the default tenant database
FINERACT_DEFAULT_TENANTDB_HOSTNAME=db
FINERACT_DEFAULT_TENANTDB_PORT=5432
FINERACT_DEFAULT_TENANTDB_UID=postgres
FINERACT_DEFAULT_TENANTDB_PWD=skdcnwauicn2ucnaecasdsajdnizucawencascdca
+1
View File
@@ -21,3 +21,4 @@ FINERACT_NODE_ID=2
FINERACT_MODE_BATCH_MANAGER_ENABLED=false
FINERACT_MODE_BATCH_WORKER_ENABLED=true
OTEL_SERVICE_NAME=fineract-worker
FINERACT_LIQUIBASE_ENABLED=false
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
-->
<configuration>
<!--
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<include resource="org/springframework/boot/logging/logback/file-appender.xml" />
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
-->
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>false</resetJUL>
</contextListener>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<withJansi>false</withJansi>
<encoder>
<pattern>%green(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%thread] %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/logs/fineract/fineract.log</file>
<append>true</append>
<prudent>true</prudent>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/var/logs/fineract/fineract.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>2</maxHistory>
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<logger name="org.springframework.transaction" level="INFO" />
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE"/>
</root>
</configuration>
+73
View File
@@ -26,4 +26,77 @@
<Match>
<Package name="~.*\.domain"/>
</Match>
<Match>
<Package name="~.*\.data"/>
</Match>
<Match>
<Package name="~org\.apache\.fineract\.integrationtests.*"/>
</Match>
<Match>
<Package name="~.*\.self\..*"/>
<Bug pattern="UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD" />
</Match>
<Match>
<Package name="~.*\.api"/>
<Bug pattern="UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD" />
</Match>
<Match>
<Package name="~.*\.api"/>
<Bug pattern="URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD" />
</Match>
<Match>
<Package name="~.*\.api"/>
<Bug pattern="UUF_UNUSED_FIELD" />
</Match>
<Match>
<Bug pattern="MS_EXPOSE_REP" />
</Match>
<Match>
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Bug pattern="NP_LOAD_OF_KNOWN_NULL_VALUE" />
</Match>
<Match>
<Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE" />
</Match>
<Match>
<Bug pattern="NP_NULL_ON_SOME_PATH" />
</Match>
<Match>
<Bug pattern="NP_NULL_PARAM_DEREF" />
</Match>
<Match>
<Bug pattern="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE" />
</Match>
<Match>
<Bug pattern="RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE" />
</Match>
<Match>
<Bug pattern="REC_CATCH_EXCEPTION" />
</Match>
<Match>
<Bug pattern="OBL_UNSATISFIED_OBLIGATION" />
</Match>
<Match>
<Bug pattern="OBL_UNSATISFIED_OBLIGATION_EXCEPTION_EDGE" />
</Match>
<Match>
<Bug pattern="MS_MUTABLE_COLLECTION_PKGPROTECT" />
</Match>
<Match>
<Bug pattern="BX_UNBOXING_IMMEDIATELY_REBOXED" />
</Match>
<Match>
<Bug pattern="RV_RETURN_VALUE_IGNORED_BAD_PRACTICE" />
</Match>
<Match>
<Bug pattern="RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT" />
</Match>
<Match>
<Bug pattern="UR_UNINIT_READ" />
</Match>
</FindBugsFilter>
-87
View File
@@ -1,87 +0,0 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
# You can replace and test a more recent version of docker compose
version: '3.7'
services:
# Backend service
fineractmysql:
image: mariadb:11.1
volumes:
- ../../fineract-db/server_collation.cnf:/etc/mysql/conf.d/server_collation.cnf
- ../../fineract-db/docker:/docker-entrypoint-initdb.d:Z,ro
restart: always
environment:
MYSQL_ROOT_PASSWORD: skdcnwauicn2ucnaecasdsajdnizucawencascdca
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "--password=skdcnwauicn2ucnaecasdsajdnizucawencascdca" ]
timeout: 10s
retries: 10
ports:
- "3306:3306"
fineract-server:
image: fineract-custom:latest
volumes:
- ../../fineract-provider/build/data:/data
healthcheck:
test: ["CMD", 'sh', '-c', 'echo -e "Checking for the availability of Fineract server deployment"; while ! nc -z "fineract-server" 8443; do sleep 1; printf "-"; done; echo -e " >> Fineract server has started";' ]
timeout: 10s
retries: 10
ports:
- 8443:8443
depends_on:
fineractmysql:
condition: service_healthy
environment:
# NOTE: node aware scheduler
- FINERACT_NODE_ID=1
# NOTE: env vars prefixed "FINERACT_HIKARI_*" are used to configure the database connection pool
- FINERACT_HIKARI_DRIVER_SOURCE_CLASS_NAME=org.mariadb.jdbc.Driver
- FINERACT_HIKARI_JDBC_URL=jdbc:mariadb://fineractmysql:3306/fineract_tenants
- FINERACT_HIKARI_USERNAME=root
- FINERACT_HIKARI_PASSWORD=skdcnwauicn2ucnaecasdsajdnizucawencascdca
# ... following variables are optional; "application.properties" contains reasonable defaults (same as here)
- FINERACT_HIKARI_MINIMUM_IDLE=3
- FINERACT_HIKARI_MAXIMUM_POOL_SIZE=10
- FINERACT_HIKARI_IDLE_TIMEOUT=60000
- FINERACT_HIKARI_CONNECTION_TIMEOUT=20000
- FINERACT_HIKARI_TEST_QUERY=SELECT 1
- FINERACT_HIKARI_AUTO_COMMIT=true
- FINERACT_HIKARI_DS_PROPERTIES_CACHE_PREP_STMTS=true
- FINERACT_HIKARI_DS_PROPERTIES_PREP_STMT_CACHE_SIZE=250
- FINERACT_HIKARI_DS_PROPERTIES_PREP_STMT_CACHE_SQL_LIMIT=2048
- FINERACT_HIKARI_DS_PROPERTIES_USE_SERVER_PREP_STMTS=true
- FINERACT_HIKARI_DS_PROPERTIES_USE_LOCAL_SESSION_STATE=true
- FINERACT_HIKARI_DS_PROPERTIES_REWRITE_BATCHED_STATEMENTS=true
- FINERACT_HIKARI_DS_PROPERTIES_CACHE_RESULT_SET_METADATA=true
- FINERACT_HIKARI_DS_PROPERTIES_CACHE_SERVER_CONFIGURATION=true
- FINERACT_HIKARI_DS_PROPERTIES_ELIDE_SET_AUTO_COMMITS=true
- FINERACT_HIKARI_DS_PROPERTIES_MAINTAIN_TIME_STATS=false
- FINERACT_HIKARI_DS_PROPERTIES_LOG_SLOW_QUERIES=true
- FINERACT_HIKARI_DS_PROPERTIES_DUMP_QUERIES_IN_EXCEPTION=true
# NOTE: env vars prefixed "FINERACT_DEFAULT_TENANTDB_*" are used to create the default tenant database
- FINERACT_DEFAULT_TENANTDB_HOSTNAME=fineractmysql
- FINERACT_DEFAULT_TENANTDB_PORT=3306
- FINERACT_DEFAULT_TENANTDB_UID=root
- FINERACT_DEFAULT_TENANTDB_PWD=skdcnwauicn2ucnaecasdsajdnizucawencascdca
- FINERACT_DEFAULT_TENANTDB_CONN_PARAMS=
- FINERACT_DEFAULT_TENANTDB_TIMEZONE=Asia/Kolkata
- FINERACT_DEFAULT_TENANTDB_IDENTIFIER=default
- FINERACT_DEFAULT_TENANTDB_NAME=fineract_default
- FINERACT_DEFAULT_TENANTDB_DESCRIPTION=Default Demo Tenant
- JAVA_TOOL_OPTIONS="-Xmx1G"
+39
View File
@@ -0,0 +1,39 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
# You can replace and test a more recent version of docker compose
version: "3.8"
services:
db:
extends:
file: ./config/docker/compose/mariadb.yml
service: mariadb
fineract:
extends:
file: ./config/docker/compose/fineract-custom.yml
service: fineract
ports:
- "8443:8443"
depends_on:
db:
condition: service_healthy
env_file:
- ./config/docker/env/fineract.env
- ./config/docker/env/fineract-common.env
- ./config/docker/env/fineract-mariadb.env
+2 -1
View File
@@ -79,8 +79,9 @@ services:
condition: service_started
env_file:
- ./config/docker/env/aws.env
- ./config/docker/env/fineract-mariadb.env
- ./config/docker/env/fineract.env
- ./config/docker/env/fineract-common.env
- ./config/docker/env/fineract-mariadb.env
- ./config/docker/env/tracing.env
- ./config/docker/env/oltp.env
- ./config/docker/env/prometheus.env
+5 -3
View File
@@ -39,8 +39,9 @@ services:
db:
condition: service_healthy
env_file:
- ./config/docker/env/fineract-postgresql.env
- ./config/docker/env/fineract-manager.env
- ./config/docker/env/fineract-common.env
- ./config/docker/env/fineract-postgresql.env
- ./config/docker/env/activemq.env
fineract-worker:
@@ -53,9 +54,10 @@ services:
ports:
- "8444-8445:8443"
depends_on:
db:
fineract-manager:
condition: service_healthy
env_file:
- ./config/docker/env/fineract-postgresql.env
- ./config/docker/env/fineract-worker.env
- ./config/docker/env/fineract-common.env
- ./config/docker/env/fineract-postgresql.env
- ./config/docker/env/activemq.env
+7 -4
View File
@@ -19,7 +19,6 @@
version: "3.8"
services:
db:
extends:
file: ./config/docker/compose/postgresql.yml
@@ -35,8 +34,10 @@ services:
db:
condition: service_healthy
env_file:
- ./config/docker/env/aws.env
- ./config/docker/env/fineract-manager.env
- ./config/docker/env/fineract-common.env
- ./config/docker/env/fineract-postgresql.env
- ./config/docker/env/aws.env
- ./config/docker/env/kafka-client-msk.env
fineract-worker:
@@ -49,9 +50,11 @@ services:
ports:
- "8444-8445:8443"
depends_on:
db:
fineract-manager:
condition: service_healthy
env_file:
- ./config/docker/env/aws.env
- ./config/docker/env/fineract-worker.env
- ./config/docker/env/fineract-common.env
- ./config/docker/env/fineract-postgresql.env
- ./config/docker/env/aws.env
- ./config/docker/env/kafka-client-msk.env
+10 -6
View File
@@ -17,12 +17,12 @@
#
# You can replace and test a more recent version of docker compose
version: '3.7'
version: "3.7"
services:
kafka:
image: 'bitnami/kafka:3.5.1-debian-11-r7'
image: "bitnami/kafka:3.5.1-debian-11-r7"
ports:
- '9092:9092'
- "9092:9092"
env_file:
- ./config/docker/env/kafka-server.env
@@ -40,9 +40,12 @@ services:
depends_on:
db:
condition: service_healthy
kafka:
condition: service_started
env_file:
- ./config/docker/env/fineract-postgresql.env
- ./config/docker/env/fineract-manager.env
- ./config/docker/env/fineract-common.env
- ./config/docker/env/fineract-postgresql.env
- ./config/docker/env/kafka-client.env
fineract-worker:
@@ -55,9 +58,10 @@ services:
ports:
- "8444-8445:8443"
depends_on:
db:
fineract-manager:
condition: service_healthy
env_file:
- ./config/docker/env/fineract-postgresql.env
- ./config/docker/env/fineract-worker.env
- ./config/docker/env/fineract-common.env
- ./config/docker/env/fineract-postgresql.env
- ./config/docker/env/kafka-client.env
+2 -1
View File
@@ -35,5 +35,6 @@ services:
db:
condition: service_healthy
env_file:
- ./config/docker/env/fineract-postgresql.env
- ./config/docker/env/fineract.env
- ./config/docker/env/fineract-common.env
- ./config/docker/env/fineract-postgresql.env
+2 -1
View File
@@ -35,5 +35,6 @@ services:
db:
condition: service_healthy
env_file:
- ./config/docker/env/fineract-mariadb.env
- ./config/docker/env/fineract.env
- ./config/docker/env/fineract-common.env
- ./config/docker/env/fineract-mariadb.env
+1 -3
View File
@@ -16,9 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
plugins {
id 'org.openapi.generator' version '6.6.0'
}
apply plugin: 'org.openapi.generator'
description = 'Fineract Client'
apply from: 'dependencies.gradle'
+2 -1
View File
@@ -21,7 +21,6 @@ dependencies {
// only handles javax annotations, not jakarta ones
implementation 'jakarta.annotation:jakarta.annotation-api:1.3.5'
implementation(
'io.swagger.core.v3:swagger-annotations-jakarta',
'com.squareup.retrofit2:retrofit',
@@ -31,6 +30,8 @@ dependencies {
'com.squareup.retrofit2:converter-gson',
'io.gsonfire:gson-fire',
'com.google.code.findbugs:jsr305',
'com.github.spotbugs:spotbugs-annotations',
'com.squareup.okhttp3:okhttp',
'com.squareup.okhttp3:logging-interceptor',
)
@@ -22,6 +22,8 @@ import java.util.List;
import org.apache.fineract.client.models.RetrieveOneResponse;
import org.apache.fineract.client.util.Calls;
import org.apache.fineract.client.util.FineractClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Demo code which is included in the fineract-doc/src/docs/en/05_client.adoc.
@@ -33,12 +35,15 @@ import org.apache.fineract.client.util.FineractClient;
*/
public class FineractClientDemo {
private static final Logger log = LoggerFactory.getLogger(FineractClientDemo.class);
void demoClient() {
// tag::documentation[]
FineractClient fineract = FineractClient.builder().baseURL("https://demo.fineract.dev/fineract-provider/api/v1/").tenant("default")
.basicAuth("mifos", "password").build();
List<RetrieveOneResponse> staff = Calls.ok(fineract.staff.retrieveAll16(1L, true, false, "ACTIVE"));
String name = staff.get(0).getDisplayName();
log.info("Display name: {}", name);
// end::documentation[]
}
@@ -20,6 +20,7 @@ package org.apache.fineract.client.test;
import static org.junit.jupiter.api.Assertions.assertThrows;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.fineract.client.util.FineractClient;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@@ -29,6 +30,7 @@ import org.junit.jupiter.api.Test;
*
* @author Michael Vorburger.ch
*/
@SuppressFBWarnings(value = "RV_EXCEPTION_NOT_THROWN", justification = "False positive")
public class FineractClientTechnicalTest {
@Test
+1 -1
View File
@@ -53,7 +53,7 @@ dependencies {
'org.springdoc:springdoc-openapi-starter-webmvc-ui',
'org.mapstruct:mapstruct',
'io.github.resilience4j:resilience4j-spring-boot2',
'io.github.resilience4j:resilience4j-spring-boot3',
'org.apache.httpcomponents:httpcore',
)
implementation ('org.springframework.boot:spring-boot-starter-data-jpa') {
@@ -70,7 +70,7 @@ public class GLClosuresApiResource {
Arrays.asList("id", "officeId", "officeName", "closingDate", "deleted", "createdDate", "lastUpdatedDate", "createdByUserId",
"createdByUsername", "lastUpdatedByUserId", "lastUpdatedByUsername"));
private final String resourceNameForPermission = "GLCLOSURE";
private static final String RESOURCE_NAME_FOR_PERMISSION = "GLCLOSURE";
private final PlatformSecurityContext context;
private final GLClosureReadPlatformService glClosureReadPlatformService;
@@ -88,7 +88,7 @@ public class GLClosuresApiResource {
public String retrieveAllClosures(@Context final UriInfo uriInfo,
@QueryParam("officeId") @Parameter(name = "officeId") final Long officeId) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
final List<GLClosureData> glClosureDatas = this.glClosureReadPlatformService.retrieveAllGLClosures(officeId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -106,7 +106,7 @@ public class GLClosuresApiResource {
public String retreiveClosure(@PathParam("glClosureId") @Parameter(description = "glClosureId") final Long glClosureId,
@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -85,7 +85,7 @@ public class GLAccountsApiResource {
"allowedAssetsTagOptions", "allowedLiabilitiesTagOptions", "allowedEquityTagOptions", "allowedIncomeTagOptions",
"allowedExpensesTagOptions", "creditAccounts", "debitAccounts"));
private final String resourceNameForPermission = "GLACCOUNT";
private static final String RESOURCE_NAME_FOR_PERMISSION = "GLACCOUNT";
private final PlatformSecurityContext context;
private final GLAccountReadPlatformService glAccountReadPlatformService;
@@ -111,7 +111,7 @@ public class GLAccountsApiResource {
public String retrieveNewAccountDetails(@Context final UriInfo uriInfo,
@QueryParam("type") @Parameter(description = "type") final Integer type) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
GLAccountData glAccountData = this.glAccountReadPlatformService.retrieveNewGLAccountDetails(type);
glAccountData = handleTemplate(glAccountData);
@@ -137,7 +137,7 @@ public class GLAccountsApiResource {
@QueryParam("disabled") @Parameter(description = "disabled") final Boolean disabled,
@QueryParam("fetchRunningBalance") @Parameter(description = "fetchRunningBalance") final boolean runningBalance) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
JournalEntryAssociationParametersData associationParametersData = new JournalEntryAssociationParametersData(false, runningBalance);
final List<GLAccountData> glAccountDatas = this.glAccountReadPlatformService.retrieveAllGLAccounts(type, searchParam, usage,
manualEntriesAllowed, disabled, associationParametersData);
@@ -159,7 +159,7 @@ public class GLAccountsApiResource {
@Context final UriInfo uriInfo,
@QueryParam("fetchRunningBalance") @Parameter(description = "fetchRunningBalance") final boolean runningBalance) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
JournalEntryAssociationParametersData associationParametersData = new JournalEntryAssociationParametersData(false, runningBalance);
@@ -18,8 +18,6 @@
*/
package org.apache.fineract.accounting.glaccount.domain;
import java.util.HashMap;
import java.util.Map;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
public enum GLAccountType {
@@ -43,7 +41,6 @@ public enum GLAccountType {
return this.code;
}
private static final Map<Integer, GLAccountType> intToEnumMap = new HashMap<>();
private static int minValue;
private static int maxValue;
@@ -53,7 +50,6 @@ public enum GLAccountType {
if (i == 0) {
minValue = type.value;
}
intToEnumMap.put(type.value, type);
if (minValue >= type.value) {
minValue = type.value;
}
@@ -86,9 +82,25 @@ public enum GLAccountType {
}
}
public static GLAccountType fromInt(final int i) {
final GLAccountType type = intToEnumMap.get(Integer.valueOf(i));
return type;
public static GLAccountType fromInt(final Integer v) {
if (v == null) {
return null;
}
switch (v) {
case 1:
return ASSET;
case 2:
return LIABILITY;
case 3:
return EQUITY;
case 4:
return INCOME;
case 5:
return EXPENSE;
default:
return null;
}
}
public static int getMinValue() {
@@ -170,8 +170,8 @@ public class GLAccountWritePlatformServiceJpaRepositoryImpl implements GLAccount
private void validateForAttachedProduct(Long glAccountId) {
String sql = "select count(*) from acc_product_mapping acc where acc.gl_account_id = ?";
try {
int count = this.jdbcTemplate.queryForObject(sql, Integer.class, glAccountId);
if (count > 0) {
Integer count = this.jdbcTemplate.queryForObject(sql, Integer.class, glAccountId);
if (count == null || count > 0) {
throw new GLAccountDisableException();
}
} catch (EmptyResultDataAccessException e) {
@@ -18,9 +18,6 @@
*/
package org.apache.fineract.accounting.journalentry.domain;
import java.util.HashMap;
import java.util.Map;
public enum JournalEntryType {
CREDIT(1, "journalEntryType.credit"), DEBIT(2, "journalEntrytType.debit");
@@ -41,16 +38,19 @@ public enum JournalEntryType {
return this.code;
}
private static final Map<Integer, JournalEntryType> intToEnumMap = new HashMap<>();
static {
for (final JournalEntryType type : JournalEntryType.values()) {
intToEnumMap.put(type.value, type);
}
public static JournalEntryType fromInt(final Integer v) {
if (v == null) {
return null;
}
public static JournalEntryType fromInt(final int i) {
return intToEnumMap.get(i);
switch (v) {
case 1:
return CREDIT;
case 2:
return DEBIT;
default:
return null;
}
}
@Override
@@ -59,11 +59,11 @@ public enum JournalEntryType {
}
public boolean isDebitType() {
return this.value.equals(JournalEntryType.DEBIT.getValue());
return this.equals(DEBIT);
}
public boolean isCreditType() {
return this.value.equals(JournalEntryType.CREDIT.getValue());
return this.equals(CREDIT);
}
}
@@ -18,9 +18,6 @@
*/
package org.apache.fineract.accounting.producttoaccountmapping.domain;
import java.util.HashMap;
import java.util.Map;
public enum PortfolioProductType {
LOAN(1, "productType.loan"), SAVING(2, "productType.saving"), CLIENT(5, "productType.client"), PROVISIONING(3,
@@ -47,33 +44,41 @@ public enum PortfolioProductType {
return this.code;
}
private static final Map<Integer, PortfolioProductType> intToEnumMap = new HashMap<>();
static {
for (final PortfolioProductType type : PortfolioProductType.values()) {
intToEnumMap.put(type.value, type);
}
public static PortfolioProductType fromInt(final Integer v) {
if (v == null) {
return null;
}
public static PortfolioProductType fromInt(final int i) {
final PortfolioProductType type = intToEnumMap.get(Integer.valueOf(i));
return type;
switch (v) {
case 1:
return LOAN;
case 2:
return SAVING;
case 3:
return CLIENT;
case 4:
return PROVISIONING;
case 5:
return SHARES;
default:
return null;
}
}
public boolean isSavingProduct() {
return this.value.equals(PortfolioProductType.SAVING.getValue());
return this.equals(SAVING);
}
public boolean isLoanProduct() {
return this.value.equals(PortfolioProductType.LOAN.getValue());
return this.equals(LOAN);
}
public boolean isClient() {
return this.value.equals(PortfolioProductType.CLIENT.getValue());
return this.equals(CLIENT);
}
public boolean isShareProduct() {
return this.value.equals(PortfolioProductType.SHARES.getValue());
return this.equals(SHARES);
}
}
@@ -26,6 +26,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.accounting.common.AccountingConstants.CashAccountsForLoan;
@@ -99,7 +100,7 @@ public class ProductToGLAccountMappingHelper {
throw new ProductToGLAccountMappingNotFoundException(portfolioProductType, productId, accountTypeName);
}
} else {
if (!accountMapping.getGlAccount().getId().equals(accountId)) {
if (accountMapping.getGlAccount() != null && !Objects.equals(accountMapping.getGlAccount().getId(), accountId)) {
final GLAccount glAccount = getAccountByIdAndType(paramName, expectedAccountType, accountId);
changes.put(paramName, accountId);
accountMapping.setGlAccount(glAccount);
@@ -124,7 +125,7 @@ public class ProductToGLAccountMappingHelper {
ProductToGLAccountMapping newAccountMapping = new ProductToGLAccountMapping().setGlAccount(glAccount)
.setProductId(productId).setProductType(portfolioProductType.getValue()).setFinancialAccountType(accountTypeId);
this.accountMappingRepository.saveAndFlush(newAccountMapping);
} else if (!accountMapping.getGlAccount().getId().equals(accountId)) {
} else if (accountMapping.getGlAccount() != null && !Objects.equals(accountMapping.getGlAccount().getId(), accountId)) {
final GLAccount glAccount = getAccountByIdAndType(paramName, expectedAccountType, accountId);
changes.put(paramName, accountId);
accountMapping.setGlAccount(glAccount);
@@ -272,14 +273,11 @@ public class ProductToGLAccountMappingHelper {
this.accountMappingRepository.delete(chargeToIncomeAccountMapping);
}
}
// create new mappings
final Set<Long> incomingCharges = inputChargeToIncomeAccountMap.keySet();
incomingCharges.removeAll(existingCharges);
// incomingPaymentTypes now only contains the newly added
// payment Type mappings
for (final Long newCharge : incomingCharges) {
final Long newGLAccountId = inputChargeToIncomeAccountMap.get(newCharge);
saveChargeToFundSourceMapping(productId, newCharge, newGLAccountId, portfolioProductType, isPenalty);
// only the newly added
for (Map.Entry<Long, Long> entry : inputChargeToIncomeAccountMap.entrySet().stream()
.filter(e -> !existingCharges.contains(e.getKey())).toList()) {
saveChargeToFundSourceMapping(productId, entry.getKey(), entry.getValue(), portfolioProductType, isPenalty);
}
}
}
@@ -321,7 +319,7 @@ public class ProductToGLAccountMappingHelper {
}
// If input map is empty, delete all existing mappings
if (inputPaymentChannelFundSourceMap.size() == 0) {
if (inputPaymentChannelFundSourceMap.isEmpty()) {
this.accountMappingRepository.deleteAllInBatch(existingPaymentChannelToFundSourceMappings);
} /**
* Else, <br/>
@@ -348,14 +346,11 @@ public class ProductToGLAccountMappingHelper {
this.accountMappingRepository.delete(existingPaymentChannelToFundSourceMapping);
}
}
// create new mappings
final Set<Long> incomingPaymentTypes = inputPaymentChannelFundSourceMap.keySet();
incomingPaymentTypes.removeAll(existingPaymentTypes);
// incomingPaymentTypes now only contains the newly added
// payment Type mappings
for (final Long newPaymentType : incomingPaymentTypes) {
final Long newGLAccountId = inputPaymentChannelFundSourceMap.get(newPaymentType);
savePaymentChannelToFundSourceMapping(productId, newPaymentType, newGLAccountId, portfolioProductType);
// only the newly added
for (Map.Entry<Long, Long> entry : inputPaymentChannelFundSourceMap.entrySet().stream()
.filter(e -> !existingPaymentTypes.contains(e.getKey())).toList()) {
savePaymentChannelToFundSourceMapping(productId, entry.getKey(), entry.getValue(), portfolioProductType);
}
}
}
@@ -37,7 +37,6 @@ import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.UriInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
@@ -112,7 +111,7 @@ public class BatchApiResource {
validateRequestMethodsAllowedOnInstanceType(requestList);
// Gets back the consolidated BatchResponse from BatchApiservice
List<BatchResponse> result = new ArrayList<>();
List<BatchResponse> result;
// If the request is to be handled as a Transaction. All requests will
// be rolled back on error
@@ -23,6 +23,7 @@ import static org.apache.http.HttpStatus.SC_OK;
import com.google.gson.Gson;
import com.jayway.jsonpath.JsonPathException;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.github.resilience4j.core.functions.Either;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
@@ -380,6 +381,7 @@ public class BatchApiServiceImpl implements BatchApiService {
return List.of(buildErrorResponse(requestId, statusCode, body, headers));
}
@SuppressFBWarnings(value = "BX_UNBOXING_IMMEDIATELY_REBOXED", justification = "TODO: fix this!")
private BatchResponse buildErrorResponse(Long requestId, Integer statusCode, String body, Set<Header> headers) {
return new BatchResponse().setRequestId(requestId).setStatusCode(statusCode == null ? SC_INTERNAL_SERVER_ERROR : statusCode)
.setBody(body == null ? "Request with id " + requestId + " was erroneous!" : body).setHeaders(headers);
@@ -65,7 +65,11 @@ public class CommandHandlerProvider implements ApplicationContextAware, Initiali
log.debug("Register command handler '{}' ...", commandHandlerName);
final CommandType commandType = applicationContext.findAnnotationOnBean(commandHandlerName, CommandType.class);
try {
if (commandType != null) {
registeredHandlers.put(commandType.entity() + "|" + commandType.action(), commandHandlerName);
} else {
log.error("Unable to register command handler '{}'!", commandHandlerName);
}
} catch (final Throwable th) {
log.error("Unable to register command handler '{}'!", commandHandlerName, th);
}
@@ -18,6 +18,7 @@
*/
package org.apache.fineract.commands.service;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.infrastructure.accountnumberformat.service.AccountNumberFormatConstants;
import org.apache.fineract.portfolio.client.api.ClientApiConstants;
@@ -47,6 +48,7 @@ public class CommandWrapperBuilder {
private String jobName;
private String idempotencyKey;
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "TODO: fix this!")
public CommandWrapper build() {
return new CommandWrapper(this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId, this.actionName, this.entityName,
this.entityId, this.subentityId, this.href, this.json, this.transactionId, this.productId, this.templateId,
@@ -18,10 +18,12 @@
*/
package org.apache.fineract.infrastructure.cache.service;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.cache.CacheApiConstants;
@@ -105,7 +107,7 @@ public class RuntimeDelegatingCacheManager implements CacheManager, Initializing
}
currentCacheManager = ehCacheManager;
if (currentCacheManager.getCacheNames().size() == 0) {
if (currentCacheManager.getCacheNames().isEmpty()) {
log.error("No caches configured for activated CacheManager {}", currentCacheManager);
}
}
@@ -115,10 +117,17 @@ public class RuntimeDelegatingCacheManager implements CacheManager, Initializing
return changes;
}
@SuppressFBWarnings(value = "DCN_NULLPOINTER_EXCEPTION", justification = "TODO: fix this!")
private void clearEhCache() {
Iterable<String> cacheNames = ehCacheManager.getCacheNames();
for (String cacheName : cacheNames) {
ehCacheManager.getCache(cacheName).clear();
try {
if (Objects.nonNull(ehCacheManager.getCache(cacheName))) {
Objects.requireNonNull(ehCacheManager.getCache(cacheName)).clear();
}
} catch (NullPointerException npe) {
log.warn(npe.getMessage());
}
}
}
}
@@ -38,6 +38,8 @@ public class FineractProperties {
private String idempotencyKeyHeaderName;
private Boolean insecureHttpClient;
private FineractTenantProperties tenant;
private FineractModeProperties mode;
@@ -39,6 +39,6 @@ public class IdempotentCommandProcessFailedException extends AbstractIdempotentC
@NotNull
public Integer getStatusCode() {
// If the database inconsistent we return http 500 instead of null pointer exception
return statusCode == null ? SC_INTERNAL_SERVER_ERROR : statusCode;
return statusCode == null ? Integer.valueOf(SC_INTERNAL_SERVER_ERROR) : statusCode;
}
}
@@ -736,6 +736,7 @@ public class JsonParserHelper {
/***
* TODO: Vishwas move all Locale related code to a separate Utils class
***/
@SuppressWarnings("StringSplitter")
public static Locale localeFromString(final String localeAsString) {
if (StringUtils.isBlank(localeAsString)) {
@@ -754,16 +755,16 @@ public class JsonParserHelper {
final String[] localeParts = localeAsString.split("_");
if (localeParts != null && localeParts.length == 1) {
if (localeParts.length == 1) {
languageCode = localeParts[0];
}
if (localeParts != null && localeParts.length == 2) {
if (localeParts.length == 2) {
languageCode = localeParts[0];
countryCode = localeParts[1];
}
if (localeParts != null && localeParts.length == 3) {
if (localeParts.length == 3) {
languageCode = localeParts[0];
countryCode = localeParts[1];
variantCode = localeParts[2];
@@ -23,10 +23,10 @@ import java.util.List;
public class Page<E> implements Serializable {
private final int totalFilteredRecords;
private final Integer totalFilteredRecords;
private final List<E> pageItems;
public Page(final List<E> pageItems, final int totalFilteredRecords) {
public Page(final List<E> pageItems, final Integer totalFilteredRecords) {
this.pageItems = pageItems;
this.totalFilteredRecords = totalFilteredRecords;
}
@@ -19,6 +19,7 @@
package org.apache.fineract.infrastructure.core.service;
import java.util.Locale;
import java.util.Objects;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@@ -38,4 +39,25 @@ public class PagedLocalRequest<T> extends PagedRequest<T> {
public Locale getLocaleObject() {
return locale == null ? null : JsonParserHelper.localeFromString(locale);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || !(o instanceof PagedLocalRequest)) {
return false;
}
if (!super.equals(o)) {
return false;
}
PagedLocalRequest<?> that = (PagedLocalRequest<?>) o;
return Objects.equals(dateFormat, that.dateFormat) && Objects.equals(dateTimeFormat, that.dateTimeFormat)
&& Objects.equals(locale, that.locale);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), dateFormat, dateTimeFormat, locale);
}
}
@@ -37,7 +37,7 @@ public class PagedRequest<T> {
private int page;
private int size = DEFAULT_PAGE_SIZE;
private List<SortOrder> sorts = new ArrayList<>();
private final List<SortOrder> sorts = new ArrayList<>();
public Optional<T> getRequest() {
return Optional.ofNullable(request);
@@ -45,7 +45,7 @@ public class PaginationHelper {
// determine how many rows are available
final String sqlCountRows = sqlGenerator.countLastExecutedQueryResult(sqlFetchRows);
final int totalFilteredRecords;
final Integer totalFilteredRecords;
if (databaseTypeResolver.isMySQL()) {
totalFilteredRecords = jt.queryForObject(sqlCountRows, Integer.class); // NOSONAR
} else {
@@ -91,9 +91,7 @@ public enum JavaType {
OBJECT(Object.class), //
;
public static final JavaType[] VALUES = values();
private static final Map<Class<?>, JavaType> BY_TYPE = Arrays.stream(VALUES).filter(e -> e.type != null)
private static final Map<Class<?>, JavaType> BY_TYPE = Arrays.stream(values()).filter(e -> e.type != null)
.collect(Collectors.toMap(JavaType::getTypeClass, v -> v));
private final Class<?> type;
@@ -244,9 +242,9 @@ public enum JavaType {
// have to do this first to catch custom collection and map types;
// on resolve we figure out if these custom types are
// persistence-capable
for (Class<?> aType : BY_TYPE.keySet()) {
if (aType.isAssignableFrom(type)) {
return BY_TYPE.get(aType);
for (Map.Entry<Class<?>, JavaType> entry : BY_TYPE.entrySet()) {
if (entry.getKey().isAssignableFrom(type)) {
return entry.getValue();
}
}
@@ -136,11 +136,19 @@ public enum JdbcJavaType {
for (JdbcJavaType type : values()) {
DialectType dialectType = type.getDialectType(dialect);
if (dialectType.getNameResolved().equals(name)) {
// NOTE: make MySQL systems happy aka TINYINT vs BOOLEAN issue!
if (type.canBooleanType(dialect)) {
return BOOLEAN;
}
return type;
}
if (dialectType.alterNames != null) {
for (String alterName : dialectType.alterNames) {
if (alterName.equals(name)) {
// NOTE: make MySQL systems happy aka TINYINT vs BOOLEAN issue!
if (type.canBooleanType(dialect)) {
return BOOLEAN;
}
return type;
}
}
@@ -48,14 +48,15 @@ public class ExternalEventConfigurationWritePlatformServiceImpl implements Exter
final Map<String, Object> changes = new HashMap<>();
final Map<String, Boolean> changedConfigurations = new HashMap<>();
final List<ExternalEventConfiguration> modifiedConfigurations = new ArrayList<>();
for (final String eventType : commandConfigurations.keySet()) {
for (Map.Entry<String, Boolean> entry : commandConfigurations.entrySet()) {
final ExternalEventConfiguration configuration = repository
.findExternalEventConfigurationByTypeWithNotFoundDetection(eventType);
final boolean canEnable = commandConfigurations.get(eventType).booleanValue();
configuration.setEnabled(canEnable);
changedConfigurations.put(eventType, canEnable);
.findExternalEventConfigurationByTypeWithNotFoundDetection(entry.getKey());
configuration.setEnabled(entry.getValue());
changedConfigurations.put(entry.getKey(), entry.getValue());
modifiedConfigurations.add(configuration);
}
if (!modifiedConfigurations.isEmpty()) {
this.repository.saveAll(modifiedConfigurations);
}
@@ -18,6 +18,7 @@
*/
package org.apache.fineract.infrastructure.security.utils;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
@@ -28,6 +29,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
@@ -48,17 +50,18 @@ public class ColumnValidator {
this.jdbcTemplate = jdbcTemplate;
}
@SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "TODO: fix this!")
private void validateColumn(Map<String, Set<String>> tableColumnMap) {
Connection connection = null;
try {
connection = this.jdbcTemplate.getDataSource().getConnection();
connection = Objects.requireNonNull(this.jdbcTemplate.getDataSource()).getConnection();
DatabaseMetaData dbMetaData = connection.getMetaData();
ResultSet resultSet = null;
for (Map.Entry<String, Set<String>> entry : tableColumnMap.entrySet()) {
Set<String> columns = entry.getValue();
resultSet = dbMetaData.getColumns(null, null, entry.getKey(), null);
ResultSet resultSet = dbMetaData.getColumns(null, null, entry.getKey(), null);
Set<String> tableColumns = getTableColumns(resultSet);
if (columns.size() > 0 && tableColumns.size() == 0) {
if (!columns.isEmpty() && tableColumns.isEmpty()) {
throw new SQLInjectionException();
}
for (String requestedColumn : columns) {
@@ -111,17 +114,19 @@ public class ColumnValidator {
private static Map<String, Set<String>> getTableColumnMap(String schema, Map<String, Set<String>> tableColumnAliasMap) {
Map<String, Set<String>> tableColumnMap = new HashMap<>();
schema = schema.substring(schema.indexOf("from"));
for (String alias : tableColumnAliasMap.keySet()) {
int index = schema.indexOf(" " + alias + " ");
for (Map.Entry<String, Set<String>> entry : tableColumnAliasMap.entrySet()) {
int index = schema.indexOf(" " + entry.getKey() + " ");
if (index > -1) {
int startPos = 0;
int startPos;
startPos = schema.substring(0, index - 1).lastIndexOf(' ', index);
Set<String> columns = tableColumnAliasMap.get(alias);
Set<String> columns = entry.getValue();
tableColumnMap.put(schema.substring(startPos, index).trim(), columns);
} else {
throw new SQLInjectionException();
}
}
return tableColumnMap;
}
@@ -31,20 +31,21 @@ public enum HolidayStatusType {
private final Integer value;
private final String code;
public static HolidayStatusType fromInt(final Integer type) {
HolidayStatusType enumeration = HolidayStatusType.INVALID;
switch (type) {
public static HolidayStatusType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
switch (v) {
case 100:
enumeration = HolidayStatusType.PENDING_FOR_ACTIVATION;
break;
return PENDING_FOR_ACTIVATION;
case 300:
enumeration = HolidayStatusType.ACTIVE;
break;
return ACTIVE;
case 600:
enumeration = HolidayStatusType.DELETED;
break;
return DELETED;
default:
return INVALID;
}
return enumeration;
}
HolidayStatusType(final Integer value, final String code) {
@@ -52,10 +53,6 @@ public enum HolidayStatusType {
this.code = code;
}
public boolean hasStateOf(final HolidayStatusType state) {
return this.value.equals(state.getValue());
}
public Integer getValue() {
return this.value;
}
@@ -31,17 +31,19 @@ public enum RescheduleType {
this.code = code;
}
public static RescheduleType fromInt(int rescheduleTypeValue) {
RescheduleType enumerration = RescheduleType.INVALID;
switch (rescheduleTypeValue) {
public static RescheduleType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
switch (v) {
case 1:
enumerration = RescheduleType.RESCHEDULETONEXTREPAYMENTDATE;
break;
return RESCHEDULETONEXTREPAYMENTDATE;
case 2:
enumerration = RescheduleType.RESCHEDULETOSPECIFICDATE;
break;
return RESCHEDULETOSPECIFICDATE;
default:
return INVALID;
}
return enumerration;
}
public boolean isRescheduleToSpecificDate() {
@@ -18,9 +18,6 @@
*/
package org.apache.fineract.portfolio.account;
import java.util.ArrayList;
import java.util.List;
public enum PortfolioAccountType {
INVALID(0, "accountType.invalid"), //
@@ -43,20 +40,9 @@ public enum PortfolioAccountType {
return this.code;
}
public static Object[] integerValues() {
final List<Integer> values = new ArrayList<>();
for (final PortfolioAccountType enumType : values()) {
if (enumType.getValue() > 0) {
values.add(enumType.getValue());
}
}
return values.toArray();
}
public static PortfolioAccountType fromInt(final Integer type) {
PortfolioAccountType enumType = PortfolioAccountType.INVALID;
PortfolioAccountType enumType = INVALID;
if (type != null) {
switch (type) {
case 1:
@@ -65,16 +51,20 @@ public enum PortfolioAccountType {
case 2:
enumType = SAVINGS;
break;
default:
enumType = INVALID;
}
}
return enumType;
}
// TODO: bad practice and unnecessary code! why not just use the enum values themselves!?!
public boolean isSavingsAccount() {
return this.value.equals(2);
return this.equals(SAVINGS);
}
// TODO: bad practice and unnecessary code! why not just use the enum values themselves!?!
public boolean isLoanAccount() {
return this.value.equals(1);
return this.equals(LOAN);
}
}
@@ -272,12 +272,14 @@ public final class CalendarUtils {
humanReadable += " on ";
final WeekDayList weekDayList = recur.getDayList();
StringBuilder sb = new StringBuilder();
for (@SuppressWarnings("rawtypes")
final Iterator iterator = weekDayList.iterator(); iterator.hasNext();) {
final WeekDay weekDay = (WeekDay) iterator.next();
humanReadable += DayNameEnum.from(weekDay.getDay().name()).getCode();
sb.append(DayNameEnum.from(weekDay.getDay().name()).getCode());
}
humanReadable += sb.toString();
} else if (recur.getFrequency().equals(Recur.Frequency.MONTHLY)) {
NumberList nthDays = recur.getSetPosList();
@@ -684,13 +686,15 @@ public final class CalendarUtils {
* @return
*/
public static String getSqlCalendarTypeOptionsInString(final List<Integer> calendarTypeOptions) {
String sqlCalendarTypeOptions = "";
final int size = calendarTypeOptions.size();
for (int i = 0; i < size - 1; i++) {
sqlCalendarTypeOptions += calendarTypeOptions.get(i).toString() + ",";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < calendarTypeOptions.size() - 1; i++) {
sb.append(calendarTypeOptions.get(i).toString() + ",");
}
sqlCalendarTypeOptions += calendarTypeOptions.get(size - 1).toString();
return sqlCalendarTypeOptions;
sb.append(calendarTypeOptions.get(calendarTypeOptions.size() - 1).toString());
return sb.toString();
}
public static LocalDate getRecentEligibleMeetingDate(final String recurringRule, final LocalDate seedDate,
@@ -18,8 +18,7 @@
*/
package org.apache.fineract.portfolio.common.domain;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
/**
*
@@ -51,15 +50,9 @@ public enum DaysInMonthType {
return this.code;
}
// TODO: do we really need this?!?
public static Object[] integerValues() {
final List<Integer> values = new ArrayList<>();
for (final DaysInMonthType enumType : values()) {
if (enumType.getValue() > 0) {
values.add(enumType.getValue());
}
}
return values.toArray();
return Arrays.stream(values()).filter(value -> !INVALID.equals(value)).map(value -> value.value).toList().toArray();
}
public static DaysInMonthType fromInt(final Integer type) {
@@ -18,8 +18,7 @@
*/
package org.apache.fineract.portfolio.common.domain;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
/**
*
@@ -55,15 +54,9 @@ public enum DaysInYearType {
return this.code;
}
// TODO: do we really need this?!?
public static Object[] integerValues() {
final List<Integer> values = new ArrayList<>();
for (final DaysInYearType enumType : values()) {
if (enumType.getValue() > 0) {
values.add(enumType.getValue());
}
}
return values.toArray();
return Arrays.stream(values()).filter(value -> !INVALID.equals(value)).map(value -> value.value).toList().toArray();
}
public static DaysInYearType fromInt(final Integer type) {
@@ -18,8 +18,7 @@
*/
package org.apache.fineract.portfolio.common.domain;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
public enum PeriodFrequencyType {
@@ -46,62 +45,59 @@ public enum PeriodFrequencyType {
return this.code;
}
public static PeriodFrequencyType fromInt(final Integer frequency) {
PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType.INVALID;
if (frequency != null) {
switch (frequency) {
public static PeriodFrequencyType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
switch (v) {
case 0:
repaymentFrequencyType = PeriodFrequencyType.DAYS;
break;
return DAYS;
case 1:
repaymentFrequencyType = PeriodFrequencyType.WEEKS;
break;
return WEEKS;
case 2:
repaymentFrequencyType = PeriodFrequencyType.MONTHS;
break;
return MONTHS;
case 3:
repaymentFrequencyType = PeriodFrequencyType.YEARS;
break;
return YEARS;
case 4:
repaymentFrequencyType = PeriodFrequencyType.WHOLE_TERM;
break;
return WHOLE_TERM;
default:
return INVALID;
}
}
return repaymentFrequencyType;
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isMonthly() {
return this.value.equals(PeriodFrequencyType.MONTHS.getValue());
return this.equals(MONTHS);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isYearly() {
return this.value.equals(PeriodFrequencyType.YEARS.getValue());
return this.equals(YEARS);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isWeekly() {
return this.value.equals(PeriodFrequencyType.WEEKS.getValue());
return this.equals(WEEKS);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isDaily() {
return this.value.equals(PeriodFrequencyType.DAYS.getValue());
return this.equals(DAYS);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isWholeTerm() {
return this.value.equals(PeriodFrequencyType.WHOLE_TERM.getValue());
return this.equals(WHOLE_TERM);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isInvalid() {
return this.value.equals(PeriodFrequencyType.INVALID.getValue());
return this.equals(INVALID);
}
// TODO: do we really need this?!?
public static Object[] integerValues() {
final List<Integer> values = new ArrayList<>();
for (final PeriodFrequencyType enumType : values()) {
if (!enumType.isInvalid()) {
values.add(enumType.getValue());
}
}
return values.toArray();
return Arrays.stream(values()).filter(value -> !INVALID.equals(value)).map(value -> value.value).toList().toArray();
}
}
@@ -18,8 +18,7 @@
*/
package org.apache.fineract.portfolio.savings;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
/**
* An enumeration of different options available on account closure {@link FixedDepositAccount} &amp;
@@ -49,63 +48,57 @@ public enum DepositAccountOnClosureType {
return this.code;
}
public static DepositAccountOnClosureType fromInt(final Integer closureTypeValue) {
if (closureTypeValue == null) {
return DepositAccountOnClosureType.INVALID;
public static DepositAccountOnClosureType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
DepositAccountOnClosureType accountOnClosureType = DepositAccountOnClosureType.INVALID;
switch (closureTypeValue) {
switch (v) {
case 100:
accountOnClosureType = DepositAccountOnClosureType.WITHDRAW_DEPOSIT;
break;
return WITHDRAW_DEPOSIT;
case 200:
accountOnClosureType = DepositAccountOnClosureType.TRANSFER_TO_SAVINGS;
break;
return TRANSFER_TO_SAVINGS;
case 300:
accountOnClosureType = DepositAccountOnClosureType.REINVEST_PRINCIPAL_AND_INTEREST;
break;
return REINVEST_PRINCIPAL_AND_INTEREST;
case 400:
accountOnClosureType = DepositAccountOnClosureType.REINVEST_PRINCIPAL_ONLY;
break;
return REINVEST_PRINCIPAL_ONLY;
default:
return INVALID;
}
return accountOnClosureType;
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isWithdarwDeposit() {
return this.value.equals(DepositAccountOnClosureType.WITHDRAW_DEPOSIT.getValue());
return this.equals(WITHDRAW_DEPOSIT);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isTransferToSavings() {
return this.value.equals(DepositAccountOnClosureType.TRANSFER_TO_SAVINGS.getValue());
return this.equals(TRANSFER_TO_SAVINGS);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isReinvest() {
return this.value.equals(DepositAccountOnClosureType.REINVEST_PRINCIPAL_AND_INTEREST.getValue())
|| this.value.equals(DepositAccountOnClosureType.REINVEST_PRINCIPAL_ONLY.getValue());
return this.equals(REINVEST_PRINCIPAL_AND_INTEREST) || this.equals(REINVEST_PRINCIPAL_ONLY);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isReinvestPrincipal() {
return this.value.equals(DepositAccountOnClosureType.REINVEST_PRINCIPAL_ONLY.getValue());
return this.equals(REINVEST_PRINCIPAL_ONLY);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isReinvestPrincipalAndInterest() {
return this.value.equals(DepositAccountOnClosureType.REINVEST_PRINCIPAL_AND_INTEREST.getValue());
return this.equals(REINVEST_PRINCIPAL_AND_INTEREST);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isInvalid() {
return this.value.equals(DepositAccountOnClosureType.INVALID.getValue());
return this.equals(INVALID);
}
// TODO: do we really need this?!?
public static Object[] integerValues() {
final List<Integer> values = new ArrayList<>();
for (final DepositAccountOnClosureType enumType : values()) {
if (!enumType.isInvalid()) {
values.add(enumType.getValue());
}
}
return values.toArray();
return Arrays.stream(values()).filter(value -> !INVALID.equals(value)).map(value -> value.value).toList().toArray();
}
}
@@ -43,31 +43,28 @@ public enum DepositAccountOnHoldTransactionType {
return this.code;
}
public static DepositAccountOnHoldTransactionType fromInt(final Integer transactionType) {
if (transactionType == null) {
return DepositAccountOnHoldTransactionType.INVALID;
public static DepositAccountOnHoldTransactionType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
DepositAccountOnHoldTransactionType savingsAccountTransactionType = DepositAccountOnHoldTransactionType.INVALID;
switch (transactionType) {
switch (v) {
case 1:
savingsAccountTransactionType = DepositAccountOnHoldTransactionType.HOLD;
break;
return HOLD;
case 2:
savingsAccountTransactionType = DepositAccountOnHoldTransactionType.RELEASE;
break;
return RELEASE;
default:
return INVALID;
}
return savingsAccountTransactionType;
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isHold() {
return this.value.equals(DepositAccountOnHoldTransactionType.HOLD.getValue());
return this.equals(HOLD);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isRelease() {
return this.value.equals(DepositAccountOnHoldTransactionType.RELEASE.getValue());
return this.equals(RELEASE);
}
}
@@ -48,44 +48,48 @@ public enum DepositAccountType {
return this.code;
}
public static DepositAccountType fromInt(final Integer transactionType) {
if (transactionType == null) {
return DepositAccountType.INVALID;
public static DepositAccountType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
DepositAccountType depositAccountType = DepositAccountType.INVALID;
switch (transactionType) {
switch (v) {
case 100:
depositAccountType = DepositAccountType.SAVINGS_DEPOSIT;
break;
return SAVINGS_DEPOSIT;
case 200:
depositAccountType = DepositAccountType.FIXED_DEPOSIT;
break;
return FIXED_DEPOSIT;
case 300:
depositAccountType = DepositAccountType.RECURRING_DEPOSIT;
break;
return RECURRING_DEPOSIT;
case 400:
depositAccountType = DepositAccountType.CURRENT_DEPOSIT;
break;
return CURRENT_DEPOSIT;
default:
return INVALID;
}
return depositAccountType;
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isSavingsDeposit() {
return this.value.equals(DepositAccountType.SAVINGS_DEPOSIT.getValue());
return this.equals(SAVINGS_DEPOSIT);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isFixedDeposit() {
return this.value.equals(DepositAccountType.FIXED_DEPOSIT.getValue());
return this.equals(FIXED_DEPOSIT);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isRecurringDeposit() {
return this.value.equals(DepositAccountType.RECURRING_DEPOSIT.getValue());
return this.equals(RECURRING_DEPOSIT);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isCurrentDeposit() {
return this.value.equals(DepositAccountType.CURRENT_DEPOSIT.getValue());
return this.equals(CURRENT_DEPOSIT);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isInvalid() {
return this.equals(INVALID);
}
@Override
@@ -94,28 +98,15 @@ public enum DepositAccountType {
}
public String resourceName() {
String resourceName;
switch (this) {
case FIXED_DEPOSIT:
resourceName = DepositsApiConstants.FIXED_DEPOSIT_ACCOUNT_RESOURCE_NAME;
break;
return DepositsApiConstants.FIXED_DEPOSIT_ACCOUNT_RESOURCE_NAME;
case RECURRING_DEPOSIT:
resourceName = DepositsApiConstants.RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME;
break;
return DepositsApiConstants.RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME;
case SAVINGS_DEPOSIT:
resourceName = DepositsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME;
break;
return DepositsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME;
default:
resourceName = "INVALID";
break;
return "INVALID";
}
return resourceName;
}
public boolean isInvalid() {
return this.value.equals(DepositAccountType.INVALID.value);
}
}
@@ -18,8 +18,7 @@
*/
package org.apache.fineract.portfolio.savings;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
/**
* An enumeration of supported calendar periods used in savings.
@@ -45,41 +44,38 @@ public enum PreClosurePenalInterestOnType {
return this.code;
}
public static PreClosurePenalInterestOnType fromInt(final Integer type) {
PreClosurePenalInterestOnType penalInterestType = PreClosurePenalInterestOnType.INVALID;
if (type != null) {
switch (type) {
public static PreClosurePenalInterestOnType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
switch (v) {
case 1:
penalInterestType = PreClosurePenalInterestOnType.WHOLE_TERM;
break;
return WHOLE_TERM;
case 2:
penalInterestType = PreClosurePenalInterestOnType.TILL_PREMATURE_WITHDRAWAL;
break;
return TILL_PREMATURE_WITHDRAWAL;
default:
return INVALID;
}
}
return penalInterestType;
}
// TODO: do we really need this?!?
public static Object[] integerValues() {
final List<Integer> values = new ArrayList<>();
for (final PreClosurePenalInterestOnType enumType : values()) {
if (enumType.getValue() > 0) {
values.add(enumType.getValue());
}
}
return values.toArray();
return Arrays.stream(values()).filter(value -> !INVALID.equals(value)).map(value -> value.value).toList().toArray();
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isInvalid() {
return this.value.equals(PreClosurePenalInterestOnType.INVALID.value);
return this.equals(INVALID);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isWholeTerm() {
return this.value.equals(PreClosurePenalInterestOnType.WHOLE_TERM.getValue());
return this.equals(WHOLE_TERM);
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isTillPrematureWithdrawal() {
return this.value.equals(PreClosurePenalInterestOnType.TILL_PREMATURE_WITHDRAWAL.getValue());
return this.equals(TILL_PREMATURE_WITHDRAWAL);
}
}
@@ -18,8 +18,7 @@
*/
package org.apache.fineract.portfolio.savings;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
/**
* An enumeration of supported calendar periods used in savings.
@@ -45,32 +44,27 @@ public enum RecurringDepositType {
return this.code;
}
public static RecurringDepositType fromInt(final Integer type) {
RecurringDepositType rdType = RecurringDepositType.INVALID;
if (type != null) {
switch (type) {
public static RecurringDepositType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
switch (v) {
case 1:
rdType = RecurringDepositType.VOLUNTARY;
break;
return VOLUNTARY;
case 2:
rdType = RecurringDepositType.MANDATORY;
break;
return MANDATORY;
default:
return INVALID;
}
}
return rdType;
}
// TODO: do we really need this?!?
public static Object[] integerValues() {
final List<Integer> values = new ArrayList<>();
for (final RecurringDepositType enumType : values()) {
if (enumType.getValue() > 0) {
values.add(enumType.getValue());
}
}
return values.toArray();
return Arrays.stream(values()).filter(value -> !INVALID.equals(value)).map(value -> value.value).toList().toArray();
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isInvalid() {
return this.value.equals(RecurringDepositType.INVALID.value);
}
@@ -51,9 +51,7 @@ public enum SavingsAccountTransactionType {
AMOUNT_HOLD(20, "savingsAccountTransactionType.onHold", TransactionEntryType.DEBIT), //
AMOUNT_RELEASE(21, "savingsAccountTransactionType.release", TransactionEntryType.CREDIT); //
public static final SavingsAccountTransactionType[] VALUES = values();
private static final Map<Integer, SavingsAccountTransactionType> BY_ID = Arrays.stream(VALUES)
private static final Map<Integer, SavingsAccountTransactionType> BY_ID = Arrays.stream(values())
.collect(Collectors.toMap(SavingsAccountTransactionType::getValue, v -> v));
private final int value;
@@ -195,6 +193,6 @@ public enum SavingsAccountTransactionType {
@NotNull
public static List<SavingsAccountTransactionType> getFiltered(Predicate<SavingsAccountTransactionType> filter) {
return Arrays.stream(VALUES).filter(filter).toList();
return Arrays.stream(values()).filter(filter).toList();
}
}
@@ -18,8 +18,7 @@
*/
package org.apache.fineract.portfolio.savings;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
/**
* <p>
@@ -28,18 +27,15 @@ import java.util.List;
*/
public enum SavingsCompoundingInterestPeriodType {
INVALID(0, "savingsCompoundingInterestPeriodType.invalid"), //
DAILY(1, "savingsCompoundingInterestPeriodType.daily"), //
// WEEKLY(2, "savingsCompoundingInterestPeriodType.weekly"), //
// BIWEEKLY(3, "savingsCompoundingInterestPeriodType.biweekly"), //
INVALID(0, "savingsCompoundingInterestPeriodType.invalid"), DAILY(1, "savingsCompoundingInterestPeriodType.daily"),
// WEEKLY(2, "savingsCompoundingInterestPeriodType.weekly"),
// BIWEEKLY(3, "savingsCompoundingInterestPeriodType.biweekly"),
MONTHLY(4, "savingsCompoundingInterestPeriodType.monthly"),
QUATERLY(5, "savingsCompoundingInterestPeriodType.quarterly"), //
BI_ANNUAL(6, "savingsCompoundingInterestPeriodType.biannual"), //
ANNUAL(7, "savingsCompoundingInterestPeriodType.annual"); //
QUATERLY(5, "savingsCompoundingInterestPeriodType.quarterly"), BI_ANNUAL(6, "savingsCompoundingInterestPeriodType.biannual"), ANNUAL(7,
"savingsCompoundingInterestPeriodType.annual");
// NO_COMPOUNDING_SIMPLE_INTEREST(8,
// "savingsCompoundingInterestPeriodType.nocompounding");
// NO_COMPOUNDING_SIMPLE_INTEREST(8, "savingsCompoundingInterestPeriodType.nocompounding");
private final Integer value;
private final String code;
@@ -57,50 +53,35 @@ public enum SavingsCompoundingInterestPeriodType {
return this.code;
}
// TODO: do we really need this?!?
public static Object[] integerValues() {
final List<Integer> values = new ArrayList<>();
for (final SavingsCompoundingInterestPeriodType enumType : values()) {
if (enumType.getValue() > 0) {
values.add(enumType.getValue());
}
return Arrays.stream(values()).filter(value -> !INVALID.equals(value)).map(value -> value.value).toList().toArray();
}
return values.toArray();
public static SavingsCompoundingInterestPeriodType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
public static SavingsCompoundingInterestPeriodType fromInt(final Integer type) {
SavingsCompoundingInterestPeriodType repaymentFrequencyType = SavingsCompoundingInterestPeriodType.INVALID;
if (type != null) {
switch (type) {
switch (v) {
case 1:
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.DAILY;
break;
case 2:
// repaymentFrequencyType =
// SavingsCompoundingInterestPeriodType.WEEKLY;
break;
case 3:
// repaymentFrequencyType =
// SavingsCompoundingInterestPeriodType.BIWEEKLY;
break;
return DAILY;
// case 2:
// return WEEKLY;
// case 3:
// return BIWEEKLY;
case 4:
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.MONTHLY;
break;
return MONTHLY;
case 5:
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.QUATERLY;
break;
return QUATERLY;
case 6:
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.BI_ANNUAL;
break;
return BI_ANNUAL;
case 7:
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.ANNUAL;
break;
case 8:
// repaymentFrequencyType =
// SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST;
break;
return ANNUAL;
// case 8:
// return NO_COMPOUNDING_SIMPLE_INTEREST;
default:
return INVALID;
}
}
return repaymentFrequencyType;
}
}
@@ -18,8 +18,7 @@
*/
package org.apache.fineract.portfolio.savings;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
/**
*
@@ -51,29 +50,23 @@ public enum SavingsInterestCalculationDaysInYearType {
return this.code;
}
// TODO: do we really need this?!?
public static Object[] integerValues() {
final List<Integer> values = new ArrayList<>();
for (final SavingsInterestCalculationDaysInYearType enumType : values()) {
if (enumType.getValue() > 0) {
values.add(enumType.getValue());
}
return Arrays.stream(values()).filter(value -> !INVALID.equals(value)).map(value -> value.value).toList().toArray();
}
return values.toArray();
public static SavingsInterestCalculationDaysInYearType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
public static SavingsInterestCalculationDaysInYearType fromInt(final Integer type) {
SavingsInterestCalculationDaysInYearType repaymentFrequencyType = SavingsInterestCalculationDaysInYearType.INVALID;
if (type != null) {
switch (type) {
switch (v) {
case 360:
repaymentFrequencyType = SavingsInterestCalculationDaysInYearType.DAYS_360;
break;
return DAYS_360;
case 365:
repaymentFrequencyType = SavingsInterestCalculationDaysInYearType.DAYS_365;
break;
return DAYS_365;
default:
return INVALID;
}
}
return repaymentFrequencyType;
}
}
@@ -18,8 +18,7 @@
*/
package org.apache.fineract.portfolio.savings;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
/**
*
@@ -64,29 +63,23 @@ public enum SavingsInterestCalculationType {
return this.code;
}
// TODO: do we really need this?!?
public static Object[] integerValues() {
final List<Integer> values = new ArrayList<>();
for (final SavingsInterestCalculationType enumType : values()) {
if (enumType.getValue() > 0) {
values.add(enumType.getValue());
}
return Arrays.stream(values()).filter(value -> !INVALID.equals(value)).map(value -> value.value).toList().toArray();
}
return values.toArray();
public static SavingsInterestCalculationType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
public static SavingsInterestCalculationType fromInt(final Integer type) {
SavingsInterestCalculationType repaymentFrequencyType = SavingsInterestCalculationType.INVALID;
if (type != null) {
switch (type) {
switch (v) {
case 1:
repaymentFrequencyType = SavingsInterestCalculationType.DAILY_BALANCE;
break;
return DAILY_BALANCE;
case 2:
repaymentFrequencyType = SavingsInterestCalculationType.AVERAGE_DAILY_BALANCE;
break;
return AVERAGE_DAILY_BALANCE;
default:
return INVALID;
}
}
return repaymentFrequencyType;
}
}
@@ -18,8 +18,7 @@
*/
package org.apache.fineract.portfolio.savings;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
/**
* An enumeration of supported calendar periods used in savings.
@@ -48,39 +47,32 @@ public enum SavingsPeriodFrequencyType {
return this.code;
}
public static SavingsPeriodFrequencyType fromInt(final Integer type) {
SavingsPeriodFrequencyType repaymentFrequencyType = SavingsPeriodFrequencyType.INVALID;
if (type != null) {
switch (type) {
public static SavingsPeriodFrequencyType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
switch (v) {
case 0:
repaymentFrequencyType = SavingsPeriodFrequencyType.DAYS;
break;
return DAYS;
case 1:
repaymentFrequencyType = SavingsPeriodFrequencyType.WEEKS;
break;
return WEEKS;
case 2:
repaymentFrequencyType = SavingsPeriodFrequencyType.MONTHS;
break;
return MONTHS;
case 3:
repaymentFrequencyType = SavingsPeriodFrequencyType.YEARS;
break;
return YEARS;
default:
return INVALID;
}
}
return repaymentFrequencyType;
}
// TODO: why not just use the enum values... just more boilerplate code here!!
public boolean isInvalid() {
return this.value.equals(SavingsPeriodFrequencyType.INVALID.value);
return this.equals(INVALID);
}
// TODO: do we really need this?!?
public static Object[] integerValues() {
final List<Integer> values = new ArrayList<>();
for (final SavingsPeriodFrequencyType enumType : values()) {
if (!enumType.isInvalid()) {
values.add(enumType.getValue());
}
}
return values.toArray();
return Arrays.stream(values()).filter(value -> !INVALID.equals(value)).map(value -> value.value).toList().toArray();
}
}
@@ -18,8 +18,7 @@
*/
package org.apache.fineract.portfolio.savings;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
/**
* The interest posting period is the span of time at the end of which savings earned but not yet credited/posted in a
@@ -49,38 +48,29 @@ public enum SavingsPostingInterestPeriodType {
return this.code;
}
// TODO: do we really need this?!?
public static Object[] integerValues() {
final List<Integer> values = new ArrayList<>();
for (final SavingsPostingInterestPeriodType enumType : values()) {
if (enumType.getValue() > 0) {
values.add(enumType.getValue());
}
return Arrays.stream(values()).filter(value -> !INVALID.equals(value)).map(value -> value.value).toList().toArray();
}
return values.toArray();
public static SavingsPostingInterestPeriodType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
public static SavingsPostingInterestPeriodType fromInt(final Integer type) {
SavingsPostingInterestPeriodType repaymentFrequencyType = SavingsPostingInterestPeriodType.INVALID;
if (type != null) {
switch (type) {
switch (v) {
case 1:
repaymentFrequencyType = SavingsPostingInterestPeriodType.DAILY;
break;
return DAILY;
case 4:
repaymentFrequencyType = SavingsPostingInterestPeriodType.MONTHLY;
break;
return MONTHLY;
case 5:
repaymentFrequencyType = SavingsPostingInterestPeriodType.QUATERLY;
break;
return QUATERLY;
case 6:
repaymentFrequencyType = SavingsPostingInterestPeriodType.BIANNUAL;
break;
return BIANNUAL;
case 7:
repaymentFrequencyType = SavingsPostingInterestPeriodType.ANNUAL;
break;
return ANNUAL;
default:
return INVALID;
}
}
return repaymentFrequencyType;
}
}
@@ -18,8 +18,7 @@
*/
package org.apache.fineract.portfolio.savings;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
public enum SavingsWithdrawalFeesType {
@@ -43,28 +42,23 @@ public enum SavingsWithdrawalFeesType {
return this.code;
}
// TODO: do we really need this?!?
public static Object[] integerValues() {
final List<Integer> values = new ArrayList<>();
for (final SavingsWithdrawalFeesType enumType : values()) {
if (enumType.getValue() > 0) {
values.add(enumType.getValue());
}
return Arrays.stream(values()).filter(value -> !INVALID.equals(value)).map(value -> value.value).toList().toArray();
}
return values.toArray();
public static SavingsWithdrawalFeesType fromInt(final Integer v) {
if (v == null) {
return INVALID;
}
public static SavingsWithdrawalFeesType fromInt(final Integer type) {
SavingsWithdrawalFeesType withdrawalFeeType = SavingsWithdrawalFeesType.INVALID;
switch (type) {
switch (v) {
case 1:
withdrawalFeeType = FLAT;
break;
return FLAT;
case 2:
withdrawalFeeType = PERCENT_OF_AMOUNT;
break;
return PERCENT_OF_AMOUNT;
default:
return INVALID;
}
return withdrawalFeeType;
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
:years: 2015-2022
:revnumber: 1.8.0
:years: 2015-2024
:revnumber: 1.9.0-xxxx
:draft: true
:rootdir: {asciidoctorconfigdir}/..
:generated: {asciidoctorconfigdir}/build/generated/asciidoc
+1 -1
View File
@@ -30,7 +30,7 @@ asciidoctorj {
generated: "${buildDir}/generated/asciidoc",
imagesdir: "${projectDir}/src/docs/en/images",
diagramsdir: "${projectDir}/src/docs/en/diagrams",
years: '2015-2022',
years: '2015-2024',
revnumber: "${project.version}".toString(),
rootdir: "${rootDir}".toString(),
baseurl: 'fineract.apache.org',
+1 -1
View File
@@ -14,7 +14,7 @@
:source-highlighter: coderay
:experimental:
:source-language: java
:years: 2015-2022
:years: 2015-2024
:lang: en
:encoding: utf-8
:linkattrs:
+1 -1
View File
@@ -52,7 +52,7 @@ dependencies {
'org.springdoc:springdoc-openapi-starter-webmvc-ui',
'org.mapstruct:mapstruct',
'io.github.resilience4j:resilience4j-spring-boot2',
'io.github.resilience4j:resilience4j-spring-boot3',
)
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
@@ -22,7 +22,6 @@ import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.accounting.journalentry.domain.JournalEntry;
import org.apache.fineract.infrastructure.event.business.BusinessEventListener;
import org.apache.fineract.infrastructure.event.business.domain.journalentry.LoanJournalEntryCreatedBusinessEvent;
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import org.apache.fineract.investor.config.InvestorModuleIsEnabledCondition;
@@ -46,26 +45,17 @@ public class ExternalAssetOwnerJournalEntryServiceImpl implements ExternalAssetO
@PostConstruct
public void addListeners() {
businessEventNotifierService.addPostBusinessEventListener(LoanJournalEntryCreatedBusinessEvent.class,
new HandleLoanJournalEntryCreatedBusinessEvent());
}
private final class HandleLoanJournalEntryCreatedBusinessEvent implements BusinessEventListener<LoanJournalEntryCreatedBusinessEvent> {
@Override
public void onBusinessEvent(LoanJournalEntryCreatedBusinessEvent event) {
businessEventNotifierService.addPostBusinessEventListener(LoanJournalEntryCreatedBusinessEvent.class, event -> {
JournalEntry journalEntry = event.get();
createMapping(journalEntry);
}
private void createMapping(JournalEntry journalEntry) {
Long loanId = loanTransactionRepository.findLoanIdById(journalEntry.getLoanTransactionId()).orElseThrow();
externalAssetOwnerTransferLoanMappingRepository.findByLoanId(loanId).ifPresent(transferLoanMapping -> {
ExternalAssetOwnerJournalEntryMapping mapping = new ExternalAssetOwnerJournalEntryMapping();
mapping.setJournalEntry(journalEntry);
mapping.setOwner(transferLoanMapping.getOwnerTransfer().getOwner());
externalAssetOwnerJournalEntryMappingRepository.saveAndFlush(mapping);
});
}
});
}
}
@@ -21,7 +21,6 @@ package org.apache.fineract.investor.service;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.configuration.service.ConfigurationReadPlatformService;
import org.apache.fineract.infrastructure.event.business.BusinessEventListener;
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanStatusChangedBusinessEvent;
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
@@ -39,19 +38,12 @@ public class ExternalAssetOwnerLoanStatusChangePlatformServiceImpl implements Ex
@PostConstruct
public void addListeners() {
businessEventNotifierService.addPostBusinessEventListener(LoanStatusChangedBusinessEvent.class,
new ExternalAssetOwnerLoanStatusChangedListener());
}
private final class ExternalAssetOwnerLoanStatusChangedListener implements BusinessEventListener<LoanStatusChangedBusinessEvent> {
@Override
public void onBusinessEvent(LoanStatusChangedBusinessEvent event) {
businessEventNotifierService.addPostBusinessEventListener(LoanStatusChangedBusinessEvent.class, event -> {
final Loan loan = event.get();
if (configurationReadPlatformService.retrieveGlobalConfiguration(ASSET_EXTERNALIZATION_OF_NON_ACTIVE_LOANS).isEnabled()
&& (loan.isClosed() || loan.getStatus().isOverpaid())) {
loanAccountOwnerTransferService.handleLoanClosedOrOverpaid(loan);
}
}
});
}
}
+1 -1
View File
@@ -47,7 +47,7 @@ dependencies {
'org.springdoc:springdoc-openapi-starter-webmvc-ui',
'org.mapstruct:mapstruct',
'io.github.resilience4j:resilience4j-spring-boot2',
'io.github.resilience4j:resilience4j-spring-boot3',
'org.apache.httpcomponents:httpcore',
)
compileOnly 'org.projectlombok:lombok'
@@ -18,8 +18,9 @@
*/
package org.apache.fineract.portfolio.collateral.api;
import java.util.HashSet;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
public final class CollateralApiConstants {
@@ -43,16 +44,8 @@ public final class CollateralApiConstants {
this.value = value;
}
private static final Set<String> values = new HashSet<>();
static {
for (final CollateralJSONinputParams type : CollateralJSONinputParams.values()) {
values.add(type.value);
}
}
public static Set<String> getAllValues() {
return values;
return Arrays.stream(values()).map(CollateralJSONinputParams::getValue).collect(Collectors.toSet());
}
@Override
@@ -18,6 +18,7 @@
*/
package org.apache.fineract.portfolio.loanaccount.command;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.math.BigDecimal;
import java.time.LocalDate;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
@@ -49,6 +50,7 @@ public class LoanChargeCommand implements Comparable<LoanChargeCommand> {
}
@Override
@SuppressFBWarnings(value = "EQ_COMPARETO_USE_OBJECT_EQUALS", justification = "TODO: fix this! See: https://stackoverflow.com/questions/2609037/findbugs-how-to-solve-eq-compareto-use-object-equals")
public int compareTo(final LoanChargeCommand o) {
int comparison = this.chargeId.compareTo(o.chargeId);
if (comparison == 0) {
@@ -26,6 +26,7 @@ import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import org.apache.fineract.infrastructure.core.service.DateUtils;
@@ -688,7 +689,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
if (loanTransaction.isChargePayment()) {
for (final LoanChargePaidBy chargePaidBy : chargesPaidBies) {
LoanCharge loanCharge = chargePaidBy.getLoanCharge();
if (loanCharge.getId().equals(unpaidCharge.getId())) {
if (loanCharge != null && Objects.equals(loanCharge.getId(), unpaidCharge.getId())) {
chargePaidBy.setAmount(amountPaidTowardsCharge.getAmount());
}
}
@@ -18,6 +18,7 @@
*/
package org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.util.Optional;
@@ -81,6 +82,7 @@ public class ChargeOrTransaction implements Comparable<ChargeOrTransaction> {
}
@Override
@SuppressFBWarnings(value = "EQ_COMPARETO_USE_OBJECT_EQUALS", justification = "TODO: fix this! See: https://stackoverflow.com/questions/2609037/findbugs-how-to-solve-eq-compareto-use-object-equals")
public int compareTo(@NotNull ChargeOrTransaction o) {
int datePortion = this.getEffectiveDate().compareTo(o.getEffectiveDate());
if (datePortion == 0) {
@@ -221,7 +221,6 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings) {
final LocalDate transactionDate = loanTransaction.getTransactionDate();
final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency();
Money transactionAmountRemaining = transactionAmountUnprocessed;
Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency());
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency());
+6
View File
@@ -336,6 +336,12 @@ cucumber {
tags = 'not @ignore'
main = 'io.cucumber.core.cli.Main'
shorten = 'argfile'
plugin = [
'pretty',
'html:build/reports/cucumber/report.html',
'json:build/reports/cucumber/report.json',
'junit:build/reports/cucumber/report.xml'
]
}
tasks.jibDockerBuild.dependsOn(bootJar)
+10 -4
View File
@@ -18,6 +18,12 @@
*/
dependencies {
modules {
module("io.swagger.core.v3:swagger-annotations") {
replacedBy("io.swagger.core.v3:swagger-annotations-jakarta")
}
}
implementation(project(path: ':fineract-core'))
implementation(project(path: ':fineract-investor'))
implementation(project(path: ':fineract-loan'))
@@ -96,14 +102,14 @@ dependencies {
'org.springdoc:springdoc-openapi-starter-webmvc-ui',
'org.mapstruct:mapstruct',
'io.github.resilience4j:resilience4j-spring-boot2',
'io.github.resilience4j:resilience4j-spring-boot3',
)
implementation ('software.amazon.msk:aws-msk-iam-auth:2.0.0') {
implementation ('software.amazon.msk:aws-msk-iam-auth:2.0.2') {
exclude group: 'commons-logging'
}
implementation 'io.swagger.core.v3:swagger-jaxrs2-jakarta:2.2.11'
implementation 'io.swagger.core.v3:swagger-jaxrs2-jakarta:2.2.19'
implementation ('org.apache.commons:commons-email') {
exclude group: 'com.sun.mail', module: 'javax.mail'
@@ -122,7 +128,7 @@ dependencies {
implementation ('jakarta.xml.bind:jakarta.xml.bind-api') {
exclude group: 'jakarta.activation'
}
implementation ('org.apache.activemq:activemq-client') {
implementation ('org.apache.activemq:activemq-client-jakarta') {
exclude group: 'org.apache.geronimo.specs'
exclude group: 'javax.annotation', module: 'javax.annotation-api'
}
@@ -83,7 +83,7 @@ public class JournalEntriesApiResource {
"entityType", "entityId", "createdByUserId", "createdDate", "submittedOnDate", "createdByUserName", "comments", "reversed",
"referenceNumber", "currency", "transactionDetails"));
private final String resourceNameForPermission = "JOURNALENTRY";
private static final String RESOURCE_NAME_FOR_PERMISSION = "JOURNALENTRY";
private final PlatformSecurityContext context;
private final JournalEntryReadPlatformService journalEntryReadPlatformService;
@@ -125,7 +125,7 @@ public class JournalEntriesApiResource {
@QueryParam("runningBalance") @Parameter(description = "runningBalance") final boolean runningBalance,
@QueryParam("transactionDetails") @Parameter(description = "transactionDetails") final boolean transactionDetails) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
final DateFormat dateFormat = StringUtils.isBlank(rawDateFormat) ? null : new DateFormat(rawDateFormat);
@@ -174,7 +174,7 @@ public class JournalEntriesApiResource {
@QueryParam("runningBalance") @Parameter(description = "runningBalance") final boolean runningBalance,
@QueryParam("transactionDetails") @Parameter(description = "transactionDetails") final boolean transactionDetails) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
JournalEntryAssociationParametersData associationParametersData = new JournalEntryAssociationParametersData(transactionDetails,
runningBalance);
final JournalEntryData glJournalEntryData = this.journalEntryReadPlatformService.retrieveGLJournalEntryById(journalEntryId,
@@ -260,7 +260,7 @@ public class JournalEntriesApiResource {
public String retrieveOpeningBalance(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId,
@QueryParam("currencyCode") final String currencyCode) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSION);
final OfficeOpeningBalancesData officeOpeningBalancesData = this.journalEntryReadPlatformService
.retrieveOfficeOpeningBalances(officeId, currencyCode);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -724,10 +724,6 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
populateCreditDebitMaps(loanProductId, overPaymentAmount, paymentTypeId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
AccrualAccountsForLoan.GOODWILL_CREDIT.getValue(), accountMapForCredit, accountMapForDebit);
} else if (loanTransactionDTO.getTransactionType().isRepayment()) {
populateCreditDebitMaps(loanProductId, overPaymentAmount, paymentTypeId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
AccrualAccountsForLoan.FUND_SOURCE.getValue(), accountMapForCredit, accountMapForDebit);
} else {
populateCreditDebitMaps(loanProductId, overPaymentAmount, paymentTypeId, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
AccrualAccountsForLoan.FUND_SOURCE.getValue(), accountMapForCredit, accountMapForDebit);
@@ -701,10 +701,6 @@ public class CashBasedAccountingProcessorForLoan implements AccountingProcessorF
} else if (loanTransactionDTO.getTransactionType().isGoodwillCredit()) {
populateCreditDebitMaps(loanProductId, overPaymentAmount, paymentTypeId, CashAccountsForLoan.OVERPAYMENT.getValue(),
CashAccountsForLoan.GOODWILL_CREDIT.getValue(), accountMapForCredit, accountMapForDebit);
} else if (loanTransactionDTO.getTransactionType().isRepayment()) {
populateCreditDebitMaps(loanProductId, overPaymentAmount, paymentTypeId, CashAccountsForLoan.OVERPAYMENT.getValue(),
CashAccountsForLoan.FUND_SOURCE.getValue(), accountMapForCredit, accountMapForDebit);
} else {
populateCreditDebitMaps(loanProductId, overPaymentAmount, paymentTypeId, CashAccountsForLoan.OVERPAYMENT.getValue(),
CashAccountsForLoan.FUND_SOURCE.getValue(), accountMapForCredit, accountMapForDebit);

Some files were not shown because too many files have changed in this diff Show More