This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 384a52bba FINERACT-2122: Add devRun gradle task, optimize build
caching, fix deprecations
384a52bba is described below
commit 384a52bbafd6cac2b270105356bb958d7d4e3aae
Author: Kristof Jozsa <[email protected]>
AuthorDate: Sun Jan 5 22:58:21 2025 +0100
FINERACT-2122: Add devRun gradle task, optimize build caching, fix
deprecations
---
.github/workflows/build-docker-mariadb.yml | 6 +-
.github/workflows/build-docker-postgresql.yml | 6 +-
.github/workflows/build-tests.yml | 8 +-
.github/workflows/smoke-activemq.yml | 10 +-
.github/workflows/smoke-kafka.yml | 10 +-
build.gradle | 106 ++++++++++++++++---
.../groovy/org.apache.fineract.dependencies.gradle | 1 -
custom/acme/event/externalevent/build.gradle | 8 +-
custom/acme/event/starter/build.gradle | 8 +-
custom/acme/loan/cob/build.gradle | 6 +-
custom/acme/loan/job/build.gradle | 6 +-
custom/acme/loan/processor/build.gradle | 6 +-
custom/acme/loan/starter/build.gradle | 6 +-
custom/acme/note/service/build.gradle | 8 +-
custom/acme/note/starter/build.gradle | 8 +-
fineract-accounting/build.gradle | 2 +-
fineract-avro-schemas/build.gradle | 75 ++++++++++++--
fineract-client/build.gradle | 103 ++++++++++++------
fineract-core/build.gradle | 7 +-
fineract-doc/build.gradle | 16 ++-
fineract-e2e-tests-core/build.gradle | 31 ++++++
fineract-provider/build.gradle | 53 ++++++++++
.../src/main/resources/jpa/persistence.xml | 76 +++++++-------
.../org/apache/fineract/TestConfiguration.java | 11 +-
fineract-war/build.gradle | 115 +++++++++++++++++----
gradle.properties | 4 +
integration-tests/build.gradle | 12 +++
integration-tests/dependencies.gradle | 5 +-
.../integrationtests/common/SearchHelper.java | 2 +-
.../common/accounting/AccountRuleHelper.java | 2 +-
.../common/commands/MakercheckersHelper.java | 2 +-
.../common/products/DelinquencyBucketsHelper.java | 2 +-
.../common/products/DelinquencyRangesHelper.java | 2 +-
33 files changed, 552 insertions(+), 171 deletions(-)
diff --git a/.github/workflows/build-docker-mariadb.yml
b/.github/workflows/build-docker-mariadb.yml
index 00e4d164b..ab3974b80 100644
--- a/.github/workflows/build-docker-mariadb.yml
+++ b/.github/workflows/build-docker-mariadb.yml
@@ -26,11 +26,9 @@ jobs:
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
- - name: Wait for stack to come up
- 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
+ run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30
--retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
- name: Check info
- run: (( $(curl -f -k --retry 5 --retry-connrefused --connect-timeout
30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc
--chars) > 100 ))
+ run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30
--retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc
--chars) > 100 ))
diff --git a/.github/workflows/build-docker-postgresql.yml
b/.github/workflows/build-docker-postgresql.yml
index 3cbc53d90..e6b8f2d48 100644
--- a/.github/workflows/build-docker-postgresql.yml
+++ b/.github/workflows/build-docker-postgresql.yml
@@ -26,11 +26,9 @@ jobs:
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
- - name: Wait for stack to come up
- 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
+ run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30
--retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
- name: Check info
- run: (( $(curl -f -k --retry 5 --retry-connrefused --connect-timeout
30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc
--chars) > 100 ))
+ run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30
--retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc
--chars) > 100 ))
diff --git a/.github/workflows/build-tests.yml
b/.github/workflows/build-tests.yml
index cbf2f8782..e0d99ccd4 100644
--- a/.github/workflows/build-tests.yml
+++ b/.github/workflows/build-tests.yml
@@ -23,15 +23,13 @@ jobs:
- name: Setup Gradle
uses:
gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2
- name: Build the image
- run: ./gradlew --no-daemon --console=plain :fineract-provider:clean
:fineract-provider:build :fineract-provider:jibDockerBuild -x test -x cucumber
+ run: ./gradlew --no-daemon --console=plain :fineract-provider:clean
:fineract-provider:build :fineract-provider:jibDockerBuild -x test -x cucumber
-x :integration-tests:test
- name: Start the Fineract stack
run: docker compose -f docker-compose-postgresql-test-activemq.yml up
-d
- - name: Wait for stack to come up
- run: sleep 400
- 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
+ run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30
--retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
- name: Execute tests
env:
BASE_URL: https://localhost:8443
@@ -43,4 +41,4 @@ jobs:
EVENT_VERIFICATION_ENABLED: true
ACTIVEMQ_BROKER_URL: tcp://localhost:61616
ACTIVEMQ_TOPIC_NAME: events
- run: ./gradlew --no-daemon --console=plain
fineract-e2e-tests-runner:cucumber --tags 'not @Skip' allureReport
+ run: ./gradlew --no-daemon --console=plain -x test -x
:integration-tests:test fineract-e2e-tests-runner:cucumber --tags 'not @Skip'
allureReport
diff --git a/.github/workflows/smoke-activemq.yml
b/.github/workflows/smoke-activemq.yml
index 4e2bfaafd..140a05ed4 100644
--- a/.github/workflows/smoke-activemq.yml
+++ b/.github/workflows/smoke-activemq.yml
@@ -26,17 +26,15 @@ jobs:
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
- - 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
+ run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30
--retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
- name: Check health Worker1
- run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30
--retry-delay 30 https://localhost:8444/fineract-provider/actuator/health
+ run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30
--retry-delay 30 https://localhost:8444/fineract-provider/actuator/health
- name: Check info Manager
- run: (( $(curl -f -k --retry 5 --retry-connrefused --connect-timeout
30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc
--chars) > 100 ))
+ run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30
--retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc
--chars) > 100 ))
- name: Check info Worker1
- run: (( $(curl -f -k --retry 5 --retry-connrefused --connect-timeout
30 --retry-delay 30 https://localhost:8444/fineract-provider/actuator/info | wc
--chars) > 100 ))
+ run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30
--retry-delay 30 https://localhost:8444/fineract-provider/actuator/info | wc
--chars) > 100 ))
- name: Run Smoke Test with Remote COB
run: ./gradlew --no-daemon --console=plain
:integration-tests:cleanTest :integration-tests:test --tests
"org.apache.fineract.integrationtests.investor.externalassetowner.InitiateExternalAssetOwnerTransferTest.saleActiveLoanToExternalAssetOwnerAndBuybackADayLater"
-PcargoDisabled
diff --git a/.github/workflows/smoke-kafka.yml
b/.github/workflows/smoke-kafka.yml
index 1233b5520..76c4ed2c9 100644
--- a/.github/workflows/smoke-kafka.yml
+++ b/.github/workflows/smoke-kafka.yml
@@ -26,17 +26,15 @@ jobs:
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
- - 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
+ run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30
--retry-delay 30 https://localhost:8443/fineract-provider/actuator/health
- name: Check health Worker1
- run: curl -f -k --retry 10 --retry-connrefused --connect-timeout 30
--retry-delay 30 https://localhost:8444/fineract-provider/actuator/health
+ run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30
--retry-delay 30 https://localhost:8444/fineract-provider/actuator/health
- name: Check info Manager
- run: (( $(curl -f -k --retry 5 --retry-connrefused --connect-timeout
30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc
--chars) > 100 ))
+ run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30
--retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc
--chars) > 100 ))
- name: Check info Worker1
- run: (( $(curl -f -k --retry 5 --retry-connrefused --connect-timeout
30 --retry-delay 30 https://localhost:8444/fineract-provider/actuator/info | wc
--chars) > 100 ))
+ run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30
--retry-delay 30 https://localhost:8444/fineract-provider/actuator/info | wc
--chars) > 100 ))
- name: Run Smoke Test with Remote COB
run: ./gradlew --no-daemon --console=plain
:integration-tests:cleanTest :integration-tests:test --tests
"org.apache.fineract.integrationtests.investor.externalassetowner.InitiateExternalAssetOwnerTransferTest.saleActiveLoanToExternalAssetOwnerAndBuybackADayLater"
-PcargoDisabled
diff --git a/build.gradle b/build.gradle
index ad23be811..f743d4efc 100644
--- a/build.gradle
+++ b/build.gradle
@@ -150,11 +150,39 @@ allprojects {
mavenCentral()
}
+ configurations {
+ api {
+ canBeResolved = true
+ }
+ }
+
apply plugin: 'com.adarshr.test-logger'
apply plugin: 'com.diffplug.spotless'
apply plugin: 'com.github.hierynomus.license'
+ apply plugin: 'net.ltgt.errorprone'
+
+ tasks.withType(JavaCompile).configureEach {
+ options.errorprone {
+ disableWarningsInGeneratedCode = true
+ disable(
+ "CanIgnoreReturnValueSuggester",
+ "SameNameButDifferent", // Until errorprone recognizes
Lombok
+ "MultiVariableDeclaration", // Until errorprone recognizes
Lombok
+ "UnnecessaryDefaultInEnumSwitch", // FINERACT-1911
+ "AssertEqualsArgumentOrderChecker",
+ "RemoveUnusedImports" // For generated code
+ )
+ error(
+ "DefaultCharset",
+ "StringSplitter",
+ "MutablePublicArray",
+ "EqualsGetClass",
+ "FutureReturnValueIgnored"
+ )
+ }
+ }
+
apply plugin: 'org.nosphere.apache.rat'
- apply plugin: 'project-report'
apply plugin: 'com.github.jk1.dependency-license-report'
// Configuration for the sonarqube plugin is now in GitHub Actions
@@ -324,10 +352,49 @@ configure(project.fineractJavaProjects) {
apply plugin: 'java'
apply plugin: 'idea'
+
+ java {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ withSourcesJar()
+ withJavadocJar()
+ }
+
+ tasks.withType(ProcessResources) {
+ destinationDir =
layout.buildDirectory.dir('classes/java/main').get().asFile
+ }
+
+ // Add performance optimizations
+ configurations.all {
+ resolutionStrategy {
+ cacheChangingModulesFor 0, 'seconds'
+ cacheDynamicVersionsFor 0, 'seconds'
+ }
+ }
+
+ tasks.withType(JavaCompile).configureEach {
+ options.incremental = true
+ options.fork = true
+ outputs.cacheIf { true }
+ options.compilerArgs << '-parameters'
+ options.encoding = 'UTF-8'
+ options.compilerArgs << '-Xlint:unchecked'
+ options.compilerArgs << '-Xlint:deprecation'
+ if (project.hasProperty('warnings') &&
project.warnings.contains('fail')) {
+ options.compilerArgs << '-Werror'
+ }
+ if (project.hasProperty('warnings') &&
project.warnings.contains('none')) {
+ options.compilerArgs << '-nowarn'
+ }
+ if (project.plugins.hasPlugin('org.springframework.boot')) {
+ options.generatedSourceOutputDirectory =
file("$buildDir/generated/sources/annotationProcessor/java/main")
+ }
+ options.generatedSourceOutputDirectory =
file("$buildDir/generated/sources/annotationProcessor/java/main")
+ }
+
apply plugin: 'eclipse'
apply plugin: 'checkstyle'
apply plugin: 'jacoco'
- apply plugin: 'net.ltgt.errorprone'
apply plugin: 'com.github.spotbugs'
apply plugin: 'com.github.andygoossens.modernizer'
apply from:
"${rootDir}/buildSrc/src/main/groovy/org.apache.fineract.dependencies.gradle"
@@ -335,9 +402,9 @@ configure(project.fineractJavaProjects) {
group = 'org.apache.fineract'
/* define the valid syntax level for source files */
- sourceCompatibility = JavaVersion.VERSION_17
- /* define binary compatibility version */
- targetCompatibility = JavaVersion.VERSION_17
+ // sourceCompatibility = JavaVersion.VERSION_17
+ // /* define binary compatibility version */
+ // targetCompatibility = JavaVersion.VERSION_17
/*
http://stackoverflow.com/questions/19653311/jpa-repository-works-in-idea-and-production-but-not-in-gradle
*/
sourceSets.main.output.resourcesDir = sourceSets.main.java.classesDirectory
@@ -353,7 +420,6 @@ configure(project.fineractJavaProjects) {
}
configurations {
- implementation.setCanBeResolved(true)
api.setCanBeResolved(true)
}
tasks.withType(Copy) {
@@ -361,10 +427,8 @@ configure(project.fineractJavaProjects) {
}
tasks.withType(JavaCompile) {
options.compilerArgs += [
- "-Xlint:unchecked",
"-Xlint:cast",
"-Xlint:auxiliaryclass",
- "-Xlint:deprecation",
"-Xlint:dep-ann",
"-Xlint:divzero",
"-Xlint:empty",
@@ -398,6 +462,10 @@ configure(project.fineractJavaProjects) {
options.deprecation = true
}
+ check {
+ dependsOn(rat, licenseMain, licenseTest)
+ }
+
dependencies {
spotbugsPlugins 'jp.skypencil.findbugs.slf4j:bug-pattern:1.5.0@jar'
}
@@ -469,7 +537,7 @@ configure(project.fineractJavaProjects) {
reports {
html.required = true
xml.required = true
- html.destination file("${buildDir}/code-coverage")
+ html.outputLocation = layout.buildDirectory.dir('code-coverage')
}
}
@@ -479,11 +547,12 @@ configure(project.fineractJavaProjects) {
errorprone "com.google.errorprone:error_prone_core:2.35.1"
}
- tasks.withType(JavaCompile) {
+ tasks.withType(JavaCompile).configureEach {
options.errorprone {
enabled =
project.gradle.startParameter.taskNames.contains('build') ||
project.gradle.startParameter.taskNames.contains('check')
- disableWarningsInGeneratedCode = true
- excludedPaths = ".*/build/.*"
+ if (project.path == ':fineract-client') {
+ excludedPaths = '.*/build/generated/java/src/main/java/.*'
+ }
disable(
// TODO Remove disabled checks from this list, by fixing
remaining usages
"UnusedVariable",
@@ -669,6 +738,19 @@ configure(project.fineractJavaProjects) {
'java/util/Optional.get:()Ljava/lang/Object;' // Disable forcing
the usage of Optional.orElseThrow(java.util.function.Supplier<? extends X>)
]
}
+
+ tasks.withType(Javadoc) {
+ options.addStringOption('Xdoclint:none', '-quiet')
+ options.encoding = 'UTF-8'
+ // Disable strict checking to prevent build failures on invalid javadoc
+ options.addBooleanOption('html5', true)
+ // Add this if you're using Java 17 records or other modern features
+ if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) {
+ options.addBooleanOption('html5', true)
+ }
+ // Ignore any errors during javadoc generation
+ failOnError = false
+ }
}
configure(project.fineractCustomProjects) {
diff --git a/buildSrc/src/main/groovy/org.apache.fineract.dependencies.gradle
b/buildSrc/src/main/groovy/org.apache.fineract.dependencies.gradle
index 2e4b1c5a4..277a25548 100644
--- a/buildSrc/src/main/groovy/org.apache.fineract.dependencies.gradle
+++ b/buildSrc/src/main/groovy/org.apache.fineract.dependencies.gradle
@@ -130,7 +130,6 @@ dependencyManagement {
dependency 'org.mock-server:mockserver-junit-jupiter:5.15.0'
dependency 'org.webjars:webjars-locator-core:0.59'
dependency 'com.icegreen:greenmail-junit5:2.0.1'
- dependency 'com.intuit.karate:karate-junit5:1.4.1'
// fineract client dependencies
dependency "com.squareup.retrofit2:retrofit:2.11.0"
diff --git a/custom/acme/event/externalevent/build.gradle
b/custom/acme/event/externalevent/build.gradle
index bb703fb8a..57ad8a7a4 100644
--- a/custom/acme/event/externalevent/build.gradle
+++ b/custom/acme/event/externalevent/build.gradle
@@ -16,10 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-description = 'ACME Corp.: Fineract external events'
+description = 'ACME Fineract Event External Event'
-group = 'com.acme.fineract.event'
+group = 'com.acme.fineract'
-archivesBaseName = 'acme-fineract-event-externalevent'
+base {
+ archivesName = 'acme-fineract-event-externalevent'
+}
apply from: 'dependencies.gradle'
diff --git a/custom/acme/event/starter/build.gradle
b/custom/acme/event/starter/build.gradle
index 314a45cf4..a8981a976 100644
--- a/custom/acme/event/starter/build.gradle
+++ b/custom/acme/event/starter/build.gradle
@@ -16,10 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-description = 'ACME Corp.: Fineract Event Starter'
+description = 'ACME Fineract Event Starter'
-group = 'com.acme.fineract.event'
+group = 'com.acme.fineract'
-archivesBaseName = 'acme-fineract-event-starter'
+base {
+ archivesName = 'acme-fineract-event-starter'
+}
apply from: 'dependencies.gradle'
diff --git a/custom/acme/loan/cob/build.gradle
b/custom/acme/loan/cob/build.gradle
index 04ca760dc..a9ab50888 100644
--- a/custom/acme/loan/cob/build.gradle
+++ b/custom/acme/loan/cob/build.gradle
@@ -16,10 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-description = 'ACME Corp.: Fineract COB Loan'
+description = 'ACME Fineract Loan COB'
group = 'com.acme.fineract'
-archivesBaseName = 'acme-fineract-loan-cob'
+base {
+ archivesName = 'acme-fineract-loan-cob'
+}
apply from: 'dependencies.gradle'
diff --git a/custom/acme/loan/job/build.gradle
b/custom/acme/loan/job/build.gradle
index 235711ad7..d021b213a 100644
--- a/custom/acme/loan/job/build.gradle
+++ b/custom/acme/loan/job/build.gradle
@@ -16,10 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-description = 'ACME Corp.: Fineract Loan Job'
+description = 'ACME Fineract Loan Job'
group = 'com.acme.fineract'
-archivesBaseName = 'acme-fineract-loan-job'
+base {
+ archivesName = 'acme-fineract-loan-job'
+}
apply from: 'dependencies.gradle'
diff --git a/custom/acme/loan/processor/build.gradle
b/custom/acme/loan/processor/build.gradle
index c693255c9..6ff821a31 100644
--- a/custom/acme/loan/processor/build.gradle
+++ b/custom/acme/loan/processor/build.gradle
@@ -16,10 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-description = 'ACME Corp.: Fineract Loan Transaction Processors'
+description = 'ACME Fineract Loan Processor'
group = 'com.acme.fineract'
-archivesBaseName = 'acme-fineract-loan-processor'
+base {
+ archivesName = 'acme-fineract-loan-processor'
+}
apply from: 'dependencies.gradle'
diff --git a/custom/acme/loan/starter/build.gradle
b/custom/acme/loan/starter/build.gradle
index 8620f5bfd..41e4b85eb 100644
--- a/custom/acme/loan/starter/build.gradle
+++ b/custom/acme/loan/starter/build.gradle
@@ -16,10 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-description = 'ACME Corp.: Fineract COB Starter'
+description = 'ACME Fineract Loan Starter'
group = 'com.acme.fineract'
-archivesBaseName = 'acme-fineract-loan-starter'
+base {
+ archivesName = 'acme-fineract-loan-starter'
+}
apply from: 'dependencies.gradle'
diff --git a/custom/acme/note/service/build.gradle
b/custom/acme/note/service/build.gradle
index 90fdb314f..2c3adebbb 100644
--- a/custom/acme/note/service/build.gradle
+++ b/custom/acme/note/service/build.gradle
@@ -16,10 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-description = 'ACME Corp.: Fineract Note Service'
+description = 'ACME Fineract Note Service'
-group = 'com.acme.fineract.portfolio.note'
+group = 'com.acme.fineract'
-archivesBaseName = 'acme-fineract-note-service'
+base {
+ archivesName = 'acme-fineract-note-service'
+}
apply from: 'dependencies.gradle'
diff --git a/custom/acme/note/starter/build.gradle
b/custom/acme/note/starter/build.gradle
index 49bf235b5..2fb605798 100644
--- a/custom/acme/note/starter/build.gradle
+++ b/custom/acme/note/starter/build.gradle
@@ -16,10 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-description = 'ACME Corp.: Fineract Note Starter'
+description = 'ACME Fineract Note Starter'
-group = 'com.acme.fineract.portfolio.note'
+group = 'com.acme.fineract'
-archivesBaseName = 'acme-fineract-note-starter'
+base {
+ archivesName = 'acme-fineract-note-starter'
+}
apply from: 'dependencies.gradle'
diff --git a/fineract-accounting/build.gradle b/fineract-accounting/build.gradle
index 3018795aa..916069b1f 100644
--- a/fineract-accounting/build.gradle
+++ b/fineract-accounting/build.gradle
@@ -31,7 +31,7 @@ compileJava.doLast {
javaexec {
description = 'Performs EclipseLink static weaving of entity classes'
def target = source
- main 'org.eclipse.persistence.tools.weaving.jpa.StaticWeave'
+ mainClass = 'org.eclipse.persistence.tools.weaving.jpa.StaticWeave'
args '-persistenceinfo', source, source, target
classpath sourceSets.main.runtimeClasspath
}
diff --git a/fineract-avro-schemas/build.gradle
b/fineract-avro-schemas/build.gradle
index ea2051dd3..5afaaec48 100644
--- a/fineract-avro-schemas/build.gradle
+++ b/fineract-avro-schemas/build.gradle
@@ -26,18 +26,39 @@ apply plugin: 'com.github.davidmc24.gradle.plugin.avro-base'
apply from: 'dependencies.gradle'
-task preprocessAvroSchemas() {
- doLast {
- copy {
- from "$projectDir/src/main/avro"
- into "$buildDir/generated/avro/src/main/avro"
- filter { line ->
- line.replaceAll("\"bigdecimal\"", new
File("$projectDir/src/main/resources/avro-templates/bigdecimal.avsc").getText("UTF-8"))
+abstract class PreprocessAvroSchemasTask extends DefaultTask {
+ @InputDirectory
+ abstract DirectoryProperty getInputDir()
+
+ @InputFile
+ abstract RegularFileProperty getBigDecimalTemplate()
+
+ @OutputDirectory
+ abstract DirectoryProperty getOutputDir()
+
+ @TaskAction
+ def preprocess() {
+ def template = getBigDecimalTemplate().get().asFile.getText("UTF-8")
+ def input = getInputDir().get().asFile
+ def output = getOutputDir().get().asFile
+
+ input.eachFileRecurse { file ->
+ if (file.isFile()) {
+ def relativePath = input.toPath().relativize(file.toPath())
+ def targetFile = output.toPath().resolve(relativePath).toFile()
+ targetFile.parentFile.mkdirs()
+ targetFile.text = file.text.replaceAll("\"bigdecimal\"",
template)
}
}
}
}
+tasks.register('preprocessAvroSchemas', PreprocessAvroSchemasTask) {
+ inputDir = file("$projectDir/src/main/avro")
+ bigDecimalTemplate =
file("$projectDir/src/main/resources/avro-templates/bigdecimal.avsc")
+ outputDir = file("$buildDir/generated/avro/src/main/avro")
+}
+
task buildJavaSdk(type: GenerateAvroJavaTask) {
source("$buildDir/generated/avro/src/main/avro")
outputDir = file("$buildDir/generated/java/src/main/java")
@@ -53,7 +74,33 @@ spotless {
}
buildJavaSdk.dependsOn(preprocessAvroSchemas, spotlessJsonApply)
-compileJava.dependsOn(buildJavaSdk, licenseFormatMain)
+
+sourceSets {
+ main {
+ java {
+ srcDir file("$buildDir/generated/java/src/main/java")
+ }
+ resources {
+ srcDir file("$projectDir/src/main/resources")
+ srcDir file("$projectDir/src/main/avro")
+ }
+ output.dir(file("$buildDir/generated/java/src/main/java"), builtBy:
'buildJavaSdk')
+ }
+}
+
+jar {
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+ from sourceSets.main.output
+ from("$buildDir/generated/java/src/main/java") {
+ include "**/*.java"
+ }
+}
+
+compileJava {
+ dependsOn buildJavaSdk
+ source = sourceSets.main.java.srcDirs
+ options.compilerArgs += ['-parameters']
+}
java {
// keep this at Java 8, not 17
@@ -61,7 +108,10 @@ java {
targetCompatibility = JavaVersion.VERSION_1_8
}
-tasks.withType(JavaCompile) {
+tasks.withType(JavaCompile).configureEach {
+ options.errorprone {
+ enabled = false // Disable ErrorProne for this module since it
contains generated code
+ }
options.compilerArgs -= ["-Werror"]
}
@@ -74,7 +124,10 @@ test {
useJUnitPlatform()
}
-sourceSets.main.java.srcDir new File(buildDir, "generated/java/src/main/java")
-
licenseFormatMain.dependsOn buildJavaSdk
licenseMain.dependsOn licenseFormatMain
+
+tasks.named('sourcesJar') {
+ dependsOn tasks.named('buildJavaSdk')
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+}
diff --git a/fineract-client/build.gradle b/fineract-client/build.gradle
index 485493e18..a079f0a08 100644
--- a/fineract-client/build.gradle
+++ b/fineract-client/build.gradle
@@ -107,29 +107,83 @@ task buildAsciidoc(type:
org.openapitools.generator.gradle.plugin.tasks.Generate
dependsOn(':fineract-provider:resolve')
}
+// Configure source sets with proper output directories
+sourceSets {
+ main {
+ java {
+ srcDir new File(buildDir, "generated/java/src/main/java")
+ destinationDirectory =
layout.buildDirectory.dir('classes/java/main').get().asFile
+ }
+ output.resourcesDir =
layout.buildDirectory.dir('resources/main').get().asFile
+ }
+ test {
+ java {
+ destinationDirectory =
layout.buildDirectory.dir('classes/java/test').get().asFile
+ }
+ output.resourcesDir =
layout.buildDirectory.dir('resources/test').get().asFile
+ }
+}
+
+// Configure jar tasks to handle duplicates
+tasks.withType(Jar).configureEach {
+ // Handle duplicates by using the first occurrence
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+}
+
+// Improve the cleanup task to track inputs and outputs
task cleanupGeneratedJavaFiles() {
+ def tempDir = file("$buildDir/generated/temp-java")
+ def targetDir = file("$buildDir/generated/java")
+
+ inputs.dir(tempDir)
+ outputs.dir(targetDir)
+
doLast {
copy {
- from "$buildDir/generated/temp-java".toString()
- into "$buildDir/generated/java".toString()
+ from tempDir
+ into targetDir
filter { line ->
line
- // This is a temporary step to get rid of joda imports
in the generated code
- // At this point it's unknown why it's even generated,
probably it's a bug in the generator
- .replaceAll("import org\\.joda\\.time\\.\\*;", "")
- // The 3 lines below handles the cases when a request
body is not required
- .replaceAll(", \\)", ")")
- .replaceAll(", , @HeaderMap", ", @HeaderMap")
- .replaceAll("\\(, ", "(")
+ .replaceAll("import org\\.joda\\.time\\.\\*;", "")
+ .replaceAll(", \\)", ")")
+ .replaceAll(", , @HeaderMap", ", @HeaderMap")
+ .replaceAll("\\(, ", "(")
}
+ // Also set duplicates strategy for the copy task
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
}
-
dependsOn("buildJavaSdk")
}
-// TODO: @vidakovic we could provide even more client libs in different
languages (Go, Ruby, Swift etc.)
-compileJava.dependsOn(buildJavaSdk, buildTypescriptAngularSdk, buildAsciidoc,
cleanupGeneratedJavaFiles, licenseFormatMain, spotlessMiscApply)
+// Configure Java compilation
+tasks.named('compileJava') {
+ outputs.cacheIf { true }
+ dependsOn(buildJavaSdk, buildTypescriptAngularSdk, buildAsciidoc,
cleanupGeneratedJavaFiles, licenseFormatMain, spotlessMiscApply)
+ mustRunAfter(licenseFormatMain, cleanupGeneratedJavaFiles)
+}
+
+// Configure sources jar task
+tasks.named('sourcesJar') {
+ dependsOn(cleanupGeneratedJavaFiles)
+ mustRunAfter(cleanupGeneratedJavaFiles)
+
+ from(sourceSets.main.java.srcDirs) {
+ include "**/*.java"
+ }
+}
+
+// Configure license formatting
+tasks.named('licenseFormatMain') {
+ dependsOn(cleanupGeneratedJavaFiles)
+ mustRunAfter(cleanupGeneratedJavaFiles)
+ source = sourceSets.main.java.srcDirs
+}
+
+tasks.named('licenseMain') {
+ dependsOn(licenseFormatMain)
+ mustRunAfter(licenseFormatMain)
+}
java {
// keep this at Java 8, not 17; see
https://issues.apache.org/jira/browse/FINERACT-1214
@@ -137,26 +191,17 @@ java {
targetCompatibility = JavaVersion.VERSION_1_8
}
-tasks.withType(JavaCompile) {
- // the generated code in
build/generated/java/src/main/java/org/apache/fineract/client/auth/OAuthOkHttpClient.java#L71
currently uses deprecated RequestBody.create(MediaType,String)
- // TODO FINERACT-1247 why does this not work:
- // options.compilerArgs -= ["-Xlint:deprecation"]
- // options.compilerArgs += ["-Xlint:-deprecation"]
- // So we just have to use:
- options.compilerArgs -= ["-Werror"]
-}
-
-configurations {
- generatedCompileClasspath.extendsFrom implementation
- generatedRuntimeClasspath.extendsFrom runtimeClasspath
+tasks.withType(JavaCompile).configureEach {
+ options.errorprone {
+ excludedPaths = '.*/build/generated/java/src/main/java/.*'
+ }
}
test {
useJUnitPlatform()
}
-sourceSets.main.java.srcDir new File(buildDir, "generated/java/src/main/java")
-
-// NOTE: Gradle suggested these dependencies
-licenseFormatMain.dependsOn buildJavaSdk
-licenseMain.dependsOn licenseFormatMain
+configurations {
+ generatedCompileClasspath.extendsFrom implementation
+ generatedRuntimeClasspath.extendsFrom runtimeClasspath
+}
diff --git a/fineract-core/build.gradle b/fineract-core/build.gradle
index f02abf9a6..5a46fa767 100644
--- a/fineract-core/build.gradle
+++ b/fineract-core/build.gradle
@@ -31,7 +31,7 @@ compileJava.doLast {
javaexec {
description = 'Performs EclipseLink static weaving of entity classes'
def target = source
- main 'org.eclipse.persistence.tools.weaving.jpa.StaticWeave'
+ mainClass = 'org.eclipse.persistence.tools.weaving.jpa.StaticWeave'
args '-persistenceinfo', source, '-classpath',
sourceSets.main.runtimeClasspath, source, target
classpath sourceSets.main.runtimeClasspath
}
@@ -63,6 +63,11 @@ configurations {
apply from: 'dependencies.gradle'
+compileJava {
+ dependsOn ':fineract-avro-schemas:jar'
+ options.compilerArgs += ['-parameters']
+}
+
// Configuration for the modernizer plugin
// https://github.com/andygoossens/gradle-modernizer-plugin
modernizer {
diff --git a/fineract-doc/build.gradle b/fineract-doc/build.gradle
index 4338bc29b..0504c6ed8 100644
--- a/fineract-doc/build.gradle
+++ b/fineract-doc/build.gradle
@@ -25,8 +25,8 @@ asciidoctorj {
attributes = [
version: "${project.version}",
generated: "${buildDir}/generated/asciidoc",
- imagesdir: "${projectDir}/src/docs/en/images",
- diagramsdir: "${projectDir}/src/docs/en/diagrams",
+ imagesdir: "${buildDir}/generated/images",
+ diagramsdir: "${buildDir}/generated/diagrams",
years: '2015-2024',
revnumber: "${project.version}".toString(),
rootdir: "${rootDir}".toString(),
@@ -59,6 +59,16 @@ asciidoctor {
dependsOn(':fineract-client:clean', ':fineract-client:buildAsciidoc')
}
+task copyImages(type: Copy) {
+ from "${projectDir}/src/docs/en/images"
+ into "${buildDir}/generated/images"
+}
+
+task copyDiagrams(type: Copy) {
+ from "${projectDir}/src/docs/en/diagrams"
+ into "${buildDir}/generated/diagrams"
+}
+
asciidoctorPdf {
languages 'en'
@@ -71,6 +81,8 @@ asciidoctorPdf {
logging.captureStandardError LogLevel.INFO
+ dependsOn copyImages, copyDiagrams
+
// TODO: @vidakovic prepare a nicer theme
// theme 'fineract-default'
// pdfThemes {
diff --git a/fineract-e2e-tests-core/build.gradle
b/fineract-e2e-tests-core/build.gradle
index 14ccb5ff3..b5d1e35bd 100644
--- a/fineract-e2e-tests-core/build.gradle
+++ b/fineract-e2e-tests-core/build.gradle
@@ -21,10 +21,41 @@ plugins {
id 'java'
}
+// Configure source sets with proper output directories
+sourceSets {
+ test {
+ java {
+ destinationDirectory =
layout.buildDirectory.dir('classes/java/test').get().asFile
+ }
+ resources {
+ destinationDirectory =
layout.buildDirectory.dir('resources/test').get().asFile
+ }
+ }
+}
+
repositories {
mavenCentral()
}
+// Configure test compilation
+tasks.named('compileTestJava') {
+ description = 'Compiles test Java source files'
+
+ // Enable caching
+ outputs.cacheIf { true }
+
+ // Configure compiler options
+ options.compilerArgs.add("-parameters")
+
+ // Ensure proper output tracking
+ outputs.dir(sourceSets.test.java.destinationDirectory)
+ .withPropertyName("testClassesDir")
+
+ // Track annotation processor outputs
+ options.annotationProcessorGeneratedSourcesDirectory =
+
layout.buildDirectory.dir('generated/sources/annotationProcessor/java/test').get().asFile
+}
+
dependencies {
testImplementation(project(':fineract-avro-schemas'))
testImplementation(project(':fineract-client'))
diff --git a/fineract-provider/build.gradle b/fineract-provider/build.gradle
index 8f4f2121e..755ac5f32 100644
--- a/fineract-provider/build.gradle
+++ b/fineract-provider/build.gradle
@@ -82,6 +82,11 @@ resolve {
configurations {
providedRuntime // needed for Spring Boot executable WAR
providedCompile
+ implementation
+ testImplementation
+ cucumberRuntime {
+ extendsFrom testImplementation
+ }
compile() {
exclude module: 'hibernate-entitymanager'
exclude module: 'hibernate-validator'
@@ -100,6 +105,16 @@ configurations {
runtime
}
+dependencies {
+ implementation project(':fineract-core')
+ implementation 'org.springframework.boot:spring-boot-starter-test'
+ implementation 'org.mockito:mockito-core'
+ implementation 'org.mockito:mockito-junit-jupiter'
+ implementation 'org.junit.jupiter:junit-jupiter-api'
+ implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
+ implementation 'org.liquibase:liquibase-core'
+}
+
apply from: 'dependencies.gradle'
// Configuration for the modernizer plugin
@@ -352,3 +367,41 @@ spotbugsTest.dependsOn resolve
compileTestJava.dependsOn ':fineract-client:processResources',
':fineract-avro-schemas:processResources'
resolveMainClassName.dependsOn resolve
processResources.dependsOn compileJava
+
+javadoc {
+ dependsOn resolve
+}
+
+task devRun(type: org.springframework.boot.gradle.tasks.run.BootRun) {
+ description = 'Runs the application quickly for development by skipping
quality checks'
+ group = 'Application'
+
+ // Configure the build to skip quality checks
+ gradle.taskGraph.whenReady { graph ->
+ if (graph.hasTask(devRun)) {
+ tasks.matching { task ->
+ task.name in ['checkstyle', 'checkstyleMain', 'checkstyleTest',
+ 'spotlessCheck', 'spotlessApply',
+ 'spotbugsMain', 'spotbugsTest',
+ 'javadoc', 'javadocJar',
+ 'modernizer',
+ 'testClasses']
+ }.configureEach {
+ enabled = false
+ }
+ // Also disable error prone compilation flags
+ tasks.withType(JavaCompile).configureEach {
+ options.errorprone.enabled = false
+ }
+ }
+ }
+
+ // Inherit all bootRun settings
+ classpath = bootRun.classpath
+ mainClass = bootRun.mainClass
+ jvmArgs = bootRun.jvmArgs
+
+ doFirst {
+ println "Running in development mode - quality checks are disabled"
+ }
+}
diff --git a/fineract-provider/src/main/resources/jpa/persistence.xml
b/fineract-provider/src/main/resources/jpa/persistence.xml
index 4419151df..64d3e7e7b 100644
--- a/fineract-provider/src/main/resources/jpa/persistence.xml
+++ b/fineract-provider/src/main/resources/jpa/persistence.xml
@@ -32,45 +32,45 @@
<!-- Fineract core module -->
<class>org.apache.fineract.accounting.glaccount.domain.GLAccount</class>
<class>org.apache.fineract.accounting.journalentry.domain.JournalEntry</class>
-
<class>org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom</class>
-
<class>org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom</class>
<class>org.apache.fineract.infrastructure.codes.domain.Code</class>
<class>org.apache.fineract.infrastructure.codes.domain.CodeValue</class>
+
<class>org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom</class>
+
<class>org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom</class>
<class>org.apache.fineract.infrastructure.documentmanagement.domain.Image</class>
- <class>org.apache.fineract.organisation.staff.domain.Staff</class>
- <class>org.apache.fineract.organisation.office.domain.Office</class>
-
<class>org.apache.fineract.organisation.monetary.domain.OrganisationCurrency</class>
-
<class>org.apache.fineract.organisation.monetary.domain.ApplicationCurrency</class>
<class>org.apache.fineract.organisation.holiday.domain.Holiday</class>
+
<class>org.apache.fineract.organisation.monetary.domain.ApplicationCurrency</class>
+
<class>org.apache.fineract.organisation.monetary.domain.OrganisationCurrency</class>
+ <class>org.apache.fineract.organisation.office.domain.Office</class>
+ <class>org.apache.fineract.organisation.staff.domain.Staff</class>
<class>org.apache.fineract.organisation.workingdays.domain.WorkingDays</class>
- <class>org.apache.fineract.portfolio.group.domain.Group</class>
- <class>org.apache.fineract.portfolio.group.domain.GroupLevel</class>
-
<class>org.apache.fineract.portfolio.group.domain.StaffAssignmentHistory</class>
- <class>org.apache.fineract.portfolio.group.domain.GroupRole</class>
+ <class>org.apache.fineract.portfolio.calendar.domain.Calendar</class>
+
<class>org.apache.fineract.portfolio.calendar.domain.CalendarHistory</class>
+
<class>org.apache.fineract.portfolio.calendar.domain.CalendarInstance</class>
<class>org.apache.fineract.portfolio.client.domain.Client</class>
<class>org.apache.fineract.portfolio.client.domain.ClientIdentifier</class>
- <class>org.apache.fineract.portfolio.rate.domain.Rate</class>
- <class>org.apache.fineract.portfolio.fund.domain.Fund</class>
<class>org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket</class>
<class>org.apache.fineract.portfolio.delinquency.domain.DelinquencyRange</class>
-
<class>org.apache.fineract.portfolio.paymenttype.domain.PaymentType</class>
-
<class>org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail</class>
<class>org.apache.fineract.portfolio.floatingrates.domain.FloatingRate</class>
<class>org.apache.fineract.portfolio.floatingrates.domain.FloatingRatePeriod</class>
- <class>org.apache.fineract.portfolio.calendar.domain.Calendar</class>
-
<class>org.apache.fineract.portfolio.calendar.domain.CalendarHistory</class>
-
<class>org.apache.fineract.portfolio.calendar.domain.CalendarInstance</class>
+ <class>org.apache.fineract.portfolio.fund.domain.Fund</class>
+ <class>org.apache.fineract.portfolio.group.domain.Group</class>
+ <class>org.apache.fineract.portfolio.group.domain.GroupLevel</class>
+ <class>org.apache.fineract.portfolio.group.domain.GroupRole</class>
+
<class>org.apache.fineract.portfolio.group.domain.StaffAssignmentHistory</class>
+
<class>org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail</class>
+
<class>org.apache.fineract.portfolio.paymenttype.domain.PaymentType</class>
+ <class>org.apache.fineract.portfolio.rate.domain.Rate</class>
<class>org.apache.fineract.useradministration.domain.AppUser</class>
- <class>org.apache.fineract.useradministration.domain.Role</class>
- <class>org.apache.fineract.useradministration.domain.Permission</class>
<class>org.apache.fineract.useradministration.domain.AppUserClientMapping</class>
+ <class>org.apache.fineract.useradministration.domain.Permission</class>
+ <class>org.apache.fineract.useradministration.domain.Role</class>
<!-- Fineract investor module -->
<class>org.apache.fineract.investor.domain.ExternalAssetOwner</class>
+
<class>org.apache.fineract.investor.domain.ExternalAssetOwnerJournalEntryMapping</class>
<class>org.apache.fineract.investor.domain.ExternalAssetOwnerTransfer</class>
-
<class>org.apache.fineract.investor.domain.ExternalAssetOwnerTransferLoanMapping</class>
<class>org.apache.fineract.investor.domain.ExternalAssetOwnerTransferDetails</class>
-
<class>org.apache.fineract.investor.domain.ExternalAssetOwnerJournalEntryMapping</class>
<class>org.apache.fineract.investor.domain.ExternalAssetOwnerTransferJournalEntryMapping</class>
+
<class>org.apache.fineract.investor.domain.ExternalAssetOwnerTransferLoanMapping</class>
<!-- Fineract loan module -->
<class>org.apache.fineract.portfolio.collateral.domain.LoanCollateral</class>
<class>org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement</class>
@@ -79,13 +79,13 @@
<class>org.apache.fineract.portfolio.delinquency.domain.LoanDelinquencyAction</class>
<class>org.apache.fineract.portfolio.delinquency.domain.LoanDelinquencyTagHistory</class>
<class>org.apache.fineract.portfolio.delinquency.domain.LoanInstallmentDelinquencyTag</class>
-
<class>org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter</class>
<class>org.apache.fineract.portfolio.loanaccount.domain.GroupLoanIndividualMonitoringAccount</class>
<class>org.apache.fineract.portfolio.loanaccount.domain.Loan</class>
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanCharge</class>
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanChargePaidBy</class>
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement</class>
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanCreditAllocationRule</class>
+
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanCreditAllocationRule</class>
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails</class>
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanInstallmentCharge</class>
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalcualtionAdditionalDetails</class>
@@ -103,6 +103,14 @@
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction</class>
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelation</class>
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping</class>
+
<class>org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter</class>
+
<class>org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter</class>
+
<class>org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest</class>
+
<class>org.apache.fineract.portfolio.loanproduct.domain.AllocationType</class>
+
<class>org.apache.fineract.portfolio.loanproduct.domain.AllocationTypeListConverter</class>
+
<class>org.apache.fineract.portfolio.loanproduct.domain.CreditAllocationTransactionType</class>
+ <class>org.apache.fineract.portfolio.loanproduct.domain.DueType</class>
+
<class>org.apache.fineract.portfolio.loanproduct.domain.FutureInstallmentAllocationRule</class>
<class>org.apache.fineract.portfolio.loanproduct.domain.LoanProduct</class>
<class>org.apache.fineract.portfolio.loanproduct.domain.LoanProductBorrowerCycleVariations</class>
<class>org.apache.fineract.portfolio.loanproduct.domain.LoanProductConfigurableAttributes</class>
@@ -112,37 +120,35 @@
<class>org.apache.fineract.portfolio.loanproduct.domain.LoanProductInterestRecalculationDetails</class>
<class>org.apache.fineract.portfolio.loanproduct.domain.LoanProductPaymentAllocationRule</class>
<class>org.apache.fineract.portfolio.loanproduct.domain.LoanProductVariableInstallmentConfig</class>
-
<class>org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType</class>
- <class>org.apache.fineract.portfolio.loanproduct.domain.DueType</class>
-
<class>org.apache.fineract.portfolio.loanproduct.domain.AllocationType</class>
-
<class>org.apache.fineract.portfolio.loanproduct.domain.FutureInstallmentAllocationRule</class>
<class>org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationTransactionType</class>
-
<class>org.apache.fineract.portfolio.loanproduct.domain.AllocationTypeListConverter</class>
-
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanCreditAllocationRule</class>
-
<class>org.apache.fineract.portfolio.loanproduct.domain.CreditAllocationTransactionType</class>
+
<class>org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType</class>
<class>org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationTypeListConverter</class>
<class>org.apache.fineract.portfolio.loanproduct.domain.SupportedInterestRefundTypesListConverter</class>
-
<class>org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter</class>
-
<class>org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest</class>
<class>org.apache.fineract.portfolio.repaymentwithpostdatedchecks.domain.PostDatedChecks</class>
<!-- Fineract Savings module -->
<class>org.apache.fineract.interoperation.domain.InteropIdentifier</class>
<class>org.apache.fineract.portfolio.interestratechart.domain.InterestIncentives</class>
<class>org.apache.fineract.portfolio.interestratechart.domain.InterestRateChart</class>
<class>org.apache.fineract.portfolio.interestratechart.domain.InterestRateChartSlab</class>
+
<class>org.apache.fineract.portfolio.savings.domain.DepositAccountInterestIncentives</class>
<class>org.apache.fineract.portfolio.savings.domain.DepositAccountInterestRateChart</class>
<class>org.apache.fineract.portfolio.savings.domain.DepositAccountInterestRateChartSlabs</class>
-
<class>org.apache.fineract.portfolio.savings.domain.DepositAccountInterestIncentives</class>
<class>org.apache.fineract.portfolio.savings.domain.DepositAccountOnHoldTransaction</class>
<class>org.apache.fineract.portfolio.savings.domain.DepositAccountTermAndPreClosure</class>
+
<class>org.apache.fineract.portfolio.savings.domain.DepositProductRecurringDetail</class>
+
<class>org.apache.fineract.portfolio.savings.domain.DepositProductTermAndPreClosure</class>
+
<class>org.apache.fineract.portfolio.savings.domain.FixedDepositAccount</class>
+
<class>org.apache.fineract.portfolio.savings.domain.FixedDepositProduct</class>
<class>org.apache.fineract.portfolio.savings.domain.GroupSavingsIndividualMonitoring</class>
-
<class>org.apache.fineract.portfolio.savings.domain.SavingsProduct</class>
+
<class>org.apache.fineract.portfolio.savings.domain.RecurringDepositAccount</class>
+
<class>org.apache.fineract.portfolio.savings.domain.RecurringDepositProduct</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccount</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccountCharge</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccountChargePaidBy</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccountTransactionTaxDetails</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsOfficerAssignmentHistory</class>
+
<class>org.apache.fineract.portfolio.savings.domain.SavingsProduct</class>
<!-- Fineract Accounting module -->
<class>org.apache.fineract.accounting.rule.domain.AccountingRule</class>
<class>org.apache.fineract.accounting.rule.domain.AccountingTagRule</class>
@@ -151,10 +157,10 @@
<!-- Fineract Charge module -->
<class>org.apache.fineract.portfolio.charge.domain.Charge</class>
<!-- Fineract Tax module -->
- <class>org.apache.fineract.portfolio.tax.domain.TaxGroup</class>
-
<class>org.apache.fineract.portfolio.tax.domain.TaxGroupMappings</class>
<class>org.apache.fineract.portfolio.tax.domain.TaxComponent</class>
<class>org.apache.fineract.portfolio.tax.domain.TaxComponentHistory</class>
+ <class>org.apache.fineract.portfolio.tax.domain.TaxGroup</class>
+
<class>org.apache.fineract.portfolio.tax.domain.TaxGroupMappings</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.weaving" value="static" />
diff --git
a/fineract-provider/src/test/java/org/apache/fineract/TestConfiguration.java
b/fineract-provider/src/test/java/org/apache/fineract/TestConfiguration.java
index aa6a210aa..5002fae69 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/TestConfiguration.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/TestConfiguration.java
@@ -42,7 +42,6 @@ import
org.apache.fineract.infrastructure.dataqueries.service.GenericDataService
import org.apache.fineract.infrastructure.jobs.ScheduledJobRunnerConfig;
import org.apache.fineract.infrastructure.jobs.service.JobRegisterService;
import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
@@ -103,7 +102,7 @@ public class TestConfiguration {
@Primary
@Bean
public HikariDataSource tenantDataSource() {
- HikariDataSource mockDataSource = mock(HikariDataSource.class,
Mockito.RETURNS_MOCKS);
+ HikariDataSource mockDataSource = mock(HikariDataSource.class,
RETURNS_MOCKS);
return mockDataSource;
}
@@ -112,7 +111,7 @@ public class TestConfiguration {
*/
@Bean
public RoutingDataSource hikariTenantDataSource() {
- RoutingDataSource mockDataSource = mock(RoutingDataSource.class,
Mockito.RETURNS_MOCKS);
+ RoutingDataSource mockDataSource = mock(RoutingDataSource.class,
RETURNS_MOCKS);
return mockDataSource;
}
@@ -128,17 +127,17 @@ public class TestConfiguration {
@Primary
@Bean
public TenantDetailsService tenantDetailsService() {
- return mock(TenantDetailsService.class, Mockito.RETURNS_MOCKS);
+ return mock(TenantDetailsService.class, RETURNS_MOCKS);
}
@Bean
public ExtendedSpringLiquibaseFactory liquibaseFactory() {
- return mock(ExtendedSpringLiquibaseFactory.class,
Mockito.RETURNS_MOCKS);
+ return mock(ExtendedSpringLiquibaseFactory.class, RETURNS_MOCKS);
}
@Bean
public DatabaseIndependentQueryService databaseIndependentQueryService() {
- return mock(DatabaseIndependentQueryService.class,
Mockito.RETURNS_MOCKS);
+ return mock(DatabaseIndependentQueryService.class, RETURNS_MOCKS);
}
@Bean
diff --git a/fineract-war/build.gradle b/fineract-war/build.gradle
index 41c79e0ff..c7a29aad0 100644
--- a/fineract-war/build.gradle
+++ b/fineract-war/build.gradle
@@ -23,28 +23,58 @@ apply plugin: 'distribution'
apply from:
"${rootDir}/buildSrc/src/main/groovy/org.apache.fineract.dependencies.gradle"
war {
+ description = 'Assembles a WAR archive containing the web application'
archiveFileName = 'fineract-provider.war'
- from("$rootDir/licenses/binary/") {
- // notice the parens
- into "WEB-INF/licenses/binary/" // no leading slash
+
+ // Enable caching
+ outputs.cacheIf { true }
+
+ // Track inputs explicitly
+ inputs.files(project.configurations.runtimeClasspath)
+ .withPropertyName("runtimeClasspath")
+ .withPathSensitivity(PathSensitivity.RELATIVE)
+ inputs.files(project.sourceSets.main.output.classesDirs)
+ .withPropertyName("classes")
+ .withPathSensitivity(PathSensitivity.RELATIVE)
+
+ def licensesDir = file("$rootDir/licenses/binary/")
+ if (licensesDir.exists()) {
+ inputs.dir(licensesDir)
+ .withPropertyName("licenses")
+ .withPathSensitivity(PathSensitivity.RELATIVE)
+
+ from(licensesDir) {
+ into "WEB-INF/licenses/binary/"
+ }
}
- from("$rootDir/LICENSE_RELEASE") {
- // notice the parens
- into "WEB-INF/" // no leading slash
+
+ def legalFiles = [
+ file("$rootDir/LICENSE_RELEASE"),
+ file("$rootDir/NOTICE_RELEASE"),
+ file("$rootDir/DISCLAIMER")
+ ].findAll { it.exists() }
+
+ if (!legalFiles.empty) {
+ inputs.files(legalFiles)
+ .withPropertyName("legalFiles")
+ .withPathSensitivity(PathSensitivity.RELATIVE)
}
- from("$rootDir/NOTICE_RELEASE") {
- // notice the parens
- into "WEB-INF/" // no leading slash
+
+ legalFiles.each { file ->
+ from(file) {
+ into "WEB-INF/"
+ }
}
+
rename ('LICENSE_RELEASE', 'LICENSE')
rename ('NOTICE_RELEASE', 'NOTICE')
-
- from("$rootDir/DISCLAIMER") {
- // notice the parens
- into "WEB-INF/" // no leading slash
- }
+
enabled = true
archiveClassifier = ''
+
+ // Ensure reproducible output
+ preserveFileTimestamps = false
+ reproducibleFileOrder = true
}
dependencies {
@@ -64,12 +94,24 @@ dependencies {
tasks.withType(Tar) {
compression Compression.GZIP
archiveExtension = 'tar.gz'
+
+ // Enable caching for all tar tasks
+ outputs.cacheIf { true }
+
+ // Ensure reproducible output
+ preserveFileTimestamps = false
+ reproducibleFileOrder = true
}
distributions {
binary {
distributionBaseName = 'apache-fineract-binary'
contents {
+ // Track inputs explicitly for binary distribution
+ filesMatching('**/*.jar') {
+ it.path =
it.path.replaceAll('-\\d+\\.\\d+\\.\\d+(-SNAPSHOT)?', '-' + version)
+ }
+
from ("$rootDir/fineract-client/build/libs/") {
include 'fineract-client-*.jar'
}
@@ -99,19 +141,52 @@ distributions {
src {
distributionBaseName = 'apache-fineract-src'
contents {
- from "$rootDir/"
- exclude '**/build' , '.git', '**/.gradle', '.github',
'**/.settings', '**/.project', '**/.classpath', '.idea', 'out', '._.DS_Store',
'.DS_Store', 'WebContent', '**/.externalToolbuilders', '.theia', '.gitpod.yml',
'LICENSE_RELEASE', 'NOTICE_RELEASE', '**/licenses', '*.class', '**/bin',
'*.log', '.dockerignore', '**/.gitkeep'
+ // Track inputs explicitly for source distribution
+ from("$rootDir/") {
+ exclude '**/build' , '.git', '**/.gradle', '.github',
'**/.settings', '**/.project',
+ '**/.classpath', '.idea', 'out', '._.DS_Store',
'.DS_Store', 'WebContent',
+ '**/.externalToolbuilders', '.theia', '.gitpod.yml',
'LICENSE_RELEASE',
+ 'NOTICE_RELEASE', '**/licenses', '*.class', '**/bin',
'*.log', '.dockerignore',
+ '**/.gitkeep'
+
+ // Ensure consistent file paths for caching
+ eachFile { details ->
+ details.path = details.path.replace('\\', '/')
+ }
+ }
rename ('LICENSE_SOURCE', 'LICENSE')
rename ('NOTICE_SOURCE', 'NOTICE')
}
}
+}
+
+// Configure specific tar tasks
+tasks.named('binaryDistTar') {
+ description = 'Assembles the binary distribution as a tar archive'
+ outputs.cacheIf { true }
+
+ // Track dependencies explicitly
+ dependsOn(war, ':fineract-client:jar', ':fineract-avro-schemas:jar',
+ ':fineract-provider:build', ':fineract-doc:doc',
+ ':fineract-client:javadocJar', ':fineract-client:sourcesJar',
+ ':fineract-avro-schemas:javadocJar',
':fineract-avro-schemas:sourcesJar')
+
+ doLast {
+
file("${buildDir}/distributions/apache-fineract-binary-${version}.tar.gz")
+
.renameTo("${buildDir}/distributions/apache-fineract-${version}-binary.tar.gz")
+ }
+}
+
+tasks.named('srcDistTar') {
+ description = 'Assembles the source distribution as a tar archive'
+ outputs.cacheIf { true }
+
doLast {
-
file("${buildDir}/distributions/apache-fineract-binary-${version}.tar.gz").renameTo("${buildDir}/distributions/apache-fineract-${version}-binary.tar.gz")
-
file("${buildDir}/distributions/apache-fineract-src-${version}.tar.gz").renameTo("${buildDir}/distributions/apache-fineract-${version}-src.tar.gz")
+ file("${buildDir}/distributions/apache-fineract-src-${version}.tar.gz")
+
.renameTo("${buildDir}/distributions/apache-fineract-${version}-src.tar.gz")
}
}
+// Disable zip distributions as they're not needed
binaryDistZip.enabled false
srcDistZip.enabled false
-// NOTE: Gradle suggested these dependencies
-binaryDistTar.dependsOn(war, ':fineract-client:jar',
':fineract-avro-schemas:jar', ':fineract-provider:build', ':fineract-doc:doc')
diff --git a/gradle.properties b/gradle.properties
index d2b7f204f..022d5cbce 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -20,3 +20,7 @@ org.gradle.jvmargs=-Xmx6g --add-exports
jdk.compiler/com.sun.tools.javac.api=ALL
buildType=BUILD
org.gradle.caching=true
org.gradle.parallel=true
+org.gradle.daemon.idletimeout=10800000
+# Temporarily disabled until we fix configuration cache compatibility
+#org.gradle.configuration-cache=true
+org.gradle.vfs.watch=true
diff --git a/integration-tests/build.gradle b/integration-tests/build.gradle
index c5839bf35..7ef84a2c9 100644
--- a/integration-tests/build.gradle
+++ b/integration-tests/build.gradle
@@ -97,6 +97,18 @@ if (!project.hasProperty('cargoDisabled')) {
}
}
+// Configure proper test output directories
+sourceSets {
+ test {
+ output.resourcesDir =
layout.buildDirectory.dir('resources/test').get().asFile
+ java.destinationDirectory =
layout.buildDirectory.dir('classes/java/test').get().asFile
+ }
+}
+
+tasks.named('compileTestJava') {
+ outputs.cacheIf { true }
+}
+
// NOTE: Gradle suggested these dependencies
compileTestJava.dependsOn(':fineract-provider:generateGitProperties',
':fineract-provider:processResources', ':fineract-provider:resolve')
spotbugsTest.dependsOn(':fineract-provider:generateGitProperties',
':fineract-provider:processResources', ':fineract-provider:resolve')
diff --git a/integration-tests/dependencies.gradle
b/integration-tests/dependencies.gradle
index f8b4e1dbf..7d2b7bd86 100644
--- a/integration-tests/dependencies.gradle
+++ b/integration-tests/dependencies.gradle
@@ -33,9 +33,7 @@ dependencies {
project(path: ':fineract-provider', configuration:
'runtimeElements'),
project(path: ':fineract-avro-schemas', configuration:
'runtimeElements'),
project(path: ':fineract-client', configuration:
'runtimeElements'),
- project(path: ':fineract-progressive-loan', configuration:
'runtimeElements'),
- 'com.intuit.karate:karate-junit5',
- // 'com.google.code.gson:gson',
+ project(path: ':fineract-progressive-loan', configuration:
'runtimeElements')
)
testImplementation ('org.mock-server:mockserver-junit-jupiter') {
exclude group: 'com.sun.mail', module: 'mailapi'
@@ -59,4 +57,5 @@ dependencies {
testAnnotationProcessor 'org.mapstruct:mapstruct-processor'
testImplementation 'com.github.tomakehurst:wiremock-standalone'
+ testImplementation 'com.google.guava:guava:32.1.3-jre'
}
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/SearchHelper.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/SearchHelper.java
index c0c6db7ec..bb42744c4 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/SearchHelper.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/SearchHelper.java
@@ -18,8 +18,8 @@
*/
package org.apache.fineract.integrationtests.common;
+import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
-import com.linecorp.armeria.internal.shaded.guava.reflect.TypeToken;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.lang.reflect.Type;
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/AccountRuleHelper.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/AccountRuleHelper.java
index c13db44a2..f0acd3807 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/AccountRuleHelper.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/AccountRuleHelper.java
@@ -18,8 +18,8 @@
*/
package org.apache.fineract.integrationtests.common.accounting;
+import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
-import com.linecorp.armeria.internal.shaded.guava.reflect.TypeToken;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.lang.reflect.Type;
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/commands/MakercheckersHelper.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/commands/MakercheckersHelper.java
index 5a36b9993..0e1039c78 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/commands/MakercheckersHelper.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/commands/MakercheckersHelper.java
@@ -18,8 +18,8 @@
*/
package org.apache.fineract.integrationtests.common.commands;
+import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
-import com.linecorp.armeria.internal.shaded.guava.reflect.TypeToken;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.lang.reflect.Type;
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/products/DelinquencyBucketsHelper.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/products/DelinquencyBucketsHelper.java
index 32efd26da..cb9a91df3 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/products/DelinquencyBucketsHelper.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/products/DelinquencyBucketsHelper.java
@@ -22,8 +22,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
-import com.linecorp.armeria.internal.shaded.guava.reflect.TypeToken;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.lang.reflect.Type;
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/products/DelinquencyRangesHelper.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/products/DelinquencyRangesHelper.java
index 220f0ec67..9f3f9e038 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/products/DelinquencyRangesHelper.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/products/DelinquencyRangesHelper.java
@@ -18,8 +18,8 @@
*/
package org.apache.fineract.integrationtests.common.products;
+import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
-import com.linecorp.armeria.internal.shaded.guava.reflect.TypeToken;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.lang.reflect.Type;