This is an automated email from the ASF dual-hosted git repository.
aleks 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 83eb084 FINERACT-1532: Create an example for pluggability
83eb084 is described below
commit 83eb0842dcd3cc58b90c9925dd1a26b270b48ad8
Author: Aleksandar Vidakovic <[email protected]>
AuthorDate: Thu Mar 17 11:35:12 2022 +0100
FINERACT-1532: Create an example for pluggability
---
build.gradle | 18 +-
config/spotbugs/exclude.xml | 20 ++
settings.gradle => custom/foo/build.gradle | 9 +-
settings.gradle => custom/foo/service/build.gradle | 13 +-
.../foo/service/dependencies.gradle | 13 +-
.../fineract/foo/service/FooDummyServiceImpl.java | 21 +-
fineract-client/build.gradle | 3 +
fineract-client/dependencies.gradle | 4 -
.../src/test/resources/cucumber.properties | 1 +
fineract-doc/build.gradle | 3 +-
fineract-doc/src/docs/en/colophon.adoc | 1 +
fineract-doc/src/docs/en/deployment.adoc | 2 +-
.../docs/en/diagrams/custom-folder-structure.puml | 17 ++
.../docs/en/diagrams/modules-folder-structure.puml | 39 ++++
.../src/docs/en/images/apache-fineract-logo.png | Bin 0 -> 22038 bytes
fineract-doc/src/docs/en/index.adoc | 4 +
fineract-doc/src/docs/en/license.adoc | 15 ++
fineract-doc/src/docs/en/modules.adoc | 250 +++++++++++++++++++++
fineract-provider/dependencies.gradle | 6 +-
.../core/boot/ApplicationExitUtil.java | 63 ------
.../{boot => config}/WebFrontEndConfiguration.java | 2 +-
.../loanaccount/api/LoansApiResource.java | 8 +-
.../note/service/NoteReadPlatformServiceImpl.java | 4 -
.../NoteWritePlatformServiceJpaRepositoryImpl.java | 4 -
.../note/starter/NoteAutoConfiguration.java | 53 +++++
.../org/apache/fineract/TestConfiguration.java | 23 +-
.../example/DummyServiceStepDefinitions.java | 54 +++++
.../module/example/TestDefaultConfiguration.java | 15 +-
.../module/example/TestFooConfiguration.java | 17 +-
.../module/service/ServiceStepDefinitions.java | 58 +++++
.../module/service/TestDefaultConfiguration.java | 84 +++++++
.../module/service/TestOverrideConfiguration.java | 83 +++++++
.../custom/CustomNoteReadPlatformService.java | 28 ++-
.../custom/CustomNoteWritePlatformService.java | 49 ++++
.../src/test/resources/cucumber.properties | 1 +
.../features/module/modules.example.feature | 12 +
.../features/module/modules.service.feature | 14 ++
gradle.properties | 2 +-
integration-tests/build.gradle | 4 +
.../src/test/resources/cucumber.properties | 1 +
settings.gradle => module/build.gradle | 9 +-
settings.gradle => module/dummy/build.gradle | 9 +-
settings.gradle => module/dummy/core/build.gradle | 13 +-
.../dummy/core/dependencies.gradle | 12 +-
.../fineract/dummy/core/data/DummyMessage.java | 25 ++-
.../fineract/dummy/core/service/DummyService.java | 15 +-
.../dummy/service/build.gradle | 13 +-
.../dummy/service/dependencies.gradle | 13 +-
.../fineract/dummy/service/DummyServiceImpl.java | 19 +-
.../dummy/starter/build.gradle | 13 +-
.../dummy/starter/dependencies.gradle | 14 +-
.../dummy/starter/DummyAutoConfiguration.java | 24 +-
.../src/main/resources/META-INF/spring.factories | 2 +
oauth2-tests/build.gradle | 5 +
oauth2-tests/dependencies.gradle | 6 -
.../src/test/resources/cucumber.properties | 1 +
settings.gradle | 4 +
twofactor-tests/build.gradle | 5 +
twofactor-tests/dependencies.gradle | 8 +-
.../src/test/resources/cucumber.properties | 1 +
60 files changed, 972 insertions(+), 257 deletions(-)
diff --git a/build.gradle b/build.gradle
index 7a4cbf4..8bcfb04 100644
--- a/build.gradle
+++ b/build.gradle
@@ -61,7 +61,7 @@ plugins {
id 'com.github.jk1.dependency-license-report' version '2.1' apply false
id 'org.openapi.generator' version '4.3.1' apply false
id 'org.zeroturnaround.gradle.jrebel' version '1.1.11' apply false
- id 'org.springframework.boot' version '2.6.4' apply false
+ id 'org.springframework.boot' version '2.6.5' apply false
id 'net.ltgt.errorprone' version '2.0.2' apply false
id 'io.swagger.core.v3.swagger-gradle-plugin' version '2.1.13' apply false
id 'com.gorylenko.gradle-git-properties' version '2.4.0' apply false
@@ -99,6 +99,8 @@ allprojects {
mavenCentral()
}
+ apply plugin: 'idea'
+ apply plugin: 'java'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'com.adarshr.test-logger'
apply plugin: 'com.diffplug.spotless'
@@ -112,10 +114,11 @@ allprojects {
dependencyManagement {
imports {
mavenBom 'org.springframework:spring-framework-bom:5.3.17'
- mavenBom 'org.springframework.boot:spring-boot-dependencies:2.6.4'
+ mavenBom 'org.springframework.boot:spring-boot-dependencies:2.6.5'
mavenBom 'org.junit:junit-bom:5.8.2'
mavenBom 'com.fasterxml.jackson:jackson-bom:2.13.2'
mavenBom 'io.cucumber:cucumber-bom:7.2.3'
+ mavenBom 'io.netty:netty-bom:4.1.75.Final'
}
dependencies {
@@ -139,13 +142,13 @@ allprojects {
dependency 'com.jayway.jsonpath:json-path:2.7.0'
dependency 'org.apache.tika:tika-core:2.3.0'
dependency 'org.apache.httpcomponents:httpclient:4.5.13'
- dependency 'io.swagger.core.v3:swagger-annotations:2.1.13'
dependency
'jakarta.management.j2ee:jakarta.management.j2ee-api:1.1.4'
dependency 'jakarta.jms:jakarta.jms-api:2.0.3'
dependency 'jakarta.xml.bind:jakarta.xml.bind-api:2.3.3' //
Swagger needs exactly this version
dependency 'org.glassfish.jaxb:jaxb-runtime:2.3.6' // Swagger
needs exactly this version
dependency 'org.apache.activemq:activemq-broker:5.16.4'
dependency 'org.apache.bval:org.apache.bval.bundle:2.0.5'
+ dependency 'joda-time:joda-time:2.10.14'
dependency 'io.github.classgraph:classgraph:4.8.141'
dependency 'org.awaitility:awaitility:4.2.0'
@@ -191,6 +194,12 @@ allprojects {
dependency "org.bouncycastle:bcpkix-jdk15to18:1.70"
dependency "org.bouncycastle:bcprov-jdk15to18:1.70"
+
+ dependency 'io.swagger.core.v3:swagger-annotations:2.1.13'
+ dependency ('io.swagger.core.v3:swagger-jaxrs2:2.1.13') {
+ exclude 'jakarta.activation:jakarta.activation-api'
+ }
+
dependency ('org.liquibase:liquibase-core:4.9.0') {
exclude 'javax.xml.bind:jaxb-api'
}
@@ -299,6 +308,7 @@ allprojects {
'**/*.puml',
'**/*.github/**',
'**/MANIFEST.MF',
+ '**/spring.factories',
'**/*.json',
'**/*.json.template',
'**/*.txt',
@@ -641,7 +651,7 @@ configure(project.fineractJavaProjects) {
cucumber {
tags = 'not @ignore'
main = 'io.cucumber.core.cli.Main'
- shorten = "argfile"
+ shorten = 'argfile'
}
// Configuration for spotbugs plugin
diff --git a/config/spotbugs/exclude.xml b/config/spotbugs/exclude.xml
index 19a9dc0..b5c1ed4 100644
--- a/config/spotbugs/exclude.xml
+++ b/config/spotbugs/exclude.xml
@@ -1,4 +1,24 @@
<?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.
+
+-->
<FindBugsFilter
xmlns="https://github.com/spotbugs/filter/3.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
diff --git a/settings.gradle b/custom/foo/build.gradle
similarity index 79%
copy from settings.gradle
copy to custom/foo/build.gradle
index 0a304eb..9b72338 100644
--- a/settings.gradle
+++ b/custom/foo/build.gradle
@@ -16,11 +16,4 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+description = 'ACME Corp.: Fineract Foo'
diff --git a/settings.gradle b/custom/foo/service/build.gradle
similarity index 79%
copy from settings.gradle
copy to custom/foo/service/build.gradle
index 0a304eb..8a0f207 100644
--- a/settings.gradle
+++ b/custom/foo/service/build.gradle
@@ -16,11 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+description = 'ACME Corp.: Fineract Foo Service'
+
+group = 'com.acmecorp.fineract.foo.service'
+
+apply from: 'dependencies.gradle'
diff --git a/settings.gradle b/custom/foo/service/dependencies.gradle
similarity index 79%
copy from settings.gradle
copy to custom/foo/service/dependencies.gradle
index 0a304eb..517ab7d 100644
--- a/settings.gradle
+++ b/custom/foo/service/dependencies.gradle
@@ -16,11 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+
+dependencies {
+ implementation(project(':module:dummy:core'),
+ 'org.springframework:spring-context')
+}
diff --git a/settings.gradle
b/custom/foo/service/src/main/java/com/acmecorp/fineract/foo/service/FooDummyServiceImpl.java
similarity index 67%
copy from settings.gradle
copy to
custom/foo/service/src/main/java/com/acmecorp/fineract/foo/service/FooDummyServiceImpl.java
index 0a304eb..fc4323a 100644
--- a/settings.gradle
+++
b/custom/foo/service/src/main/java/com/acmecorp/fineract/foo/service/FooDummyServiceImpl.java
@@ -16,11 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+package com.acmecorp.fineract.foo.service;
+
+import org.apache.fineract.dummy.core.data.DummyMessage;
+import org.apache.fineract.dummy.core.service.DummyService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FooDummyServiceImpl implements DummyService {
+ @Override
+ public DummyMessage getMessage() {
+ return new DummyMessage("Hello: FOO!");
+ }
+}
diff --git a/fineract-client/build.gradle b/fineract-client/build.gradle
index d20c2a5..845486b 100644
--- a/fineract-client/build.gradle
+++ b/fineract-client/build.gradle
@@ -22,6 +22,9 @@ apply plugin: 'org.openapi.generator'
apply from: 'dependencies.gradle'
+// enable when all tests are migrated
+tasks.cucumber.onlyIf {false}
+
// TODO: @vidakovic we should publish this lib to Maven Central; do in
separate PR
openApiMeta {
diff --git a/fineract-client/dependencies.gradle
b/fineract-client/dependencies.gradle
index cba7dba..e497f86 100644
--- a/fineract-client/dependencies.gradle
+++ b/fineract-client/dependencies.gradle
@@ -37,10 +37,6 @@ dependencies {
testImplementation(
'org.junit.jupiter:junit-jupiter-api',
- 'io.cucumber:cucumber-core',
- 'io.cucumber:cucumber-java',
- 'io.cucumber:cucumber-java8',
- 'io.cucumber:cucumber-junit-platform-engine',
'com.google.truth:truth',
'com.google.truth.extensions:truth-java8-extension'
)
diff --git a/fineract-client/src/test/resources/cucumber.properties
b/fineract-client/src/test/resources/cucumber.properties
index d3b2786..a745f74 100644
--- a/fineract-client/src/test/resources/cucumber.properties
+++ b/fineract-client/src/test/resources/cucumber.properties
@@ -18,3 +18,4 @@
#
cucumber.publish.quiet=true
+cucumber.glue=org.apache.fineract
diff --git a/fineract-doc/build.gradle b/fineract-doc/build.gradle
index b457ada..7cfd31a 100644
--- a/fineract-doc/build.gradle
+++ b/fineract-doc/build.gradle
@@ -44,11 +44,12 @@ asciidoctorj {
version = '2.4.0'
attributes = [
+ version: "$project.version",
generated: "${buildDir}/generated/asciidoc",
imagesdir: 'images',
diagrams: 'diagrams',
years: '2015-2022',
- revnumber: "$version".toString(),
+ revnumber: "$project.version".toString(),
rootdir: "$rootDir".toString(),
baseurl: 'fineract.apache.org'
]
diff --git a/fineract-doc/src/docs/en/colophon.adoc
b/fineract-doc/src/docs/en/colophon.adoc
index 70910c4..8c8032f 100644
--- a/fineract-doc/src/docs/en/colophon.adoc
+++ b/fineract-doc/src/docs/en/colophon.adoc
@@ -32,6 +32,7 @@
| Aleksandar Vidakovic | Initial version | 2020-10-26 | 1.4.0
| Arnold Galovics | Database architecture section | 2022-03-11 | 1.7.0
+| Aleksandar Vidakovic | Module section | 2022-03-23 | 1.7.0
|===
toc::[]
diff --git a/fineract-doc/src/docs/en/deployment.adoc
b/fineract-doc/src/docs/en/deployment.adoc
index c5386f5..b3f29a6 100644
--- a/fineract-doc/src/docs/en/deployment.adoc
+++ b/fineract-doc/src/docs/en/deployment.adoc
@@ -37,4 +37,4 @@ The Fineract API client supports an insecure mode
(`FineractClient.Builder#insec
The https://www.fineract.dev demo server runs on Google Cloud.
-https://docs.google.com/presentation/d/1-VP4bNkc5kZ3B0yme_vYLiY1qpswnfz8ainnX5fp3l8/[The
Running Fineract.dev, SRE style presentation] given at _ApacheCon 20202_ has
some related background.
+https://docs.google.com/presentation/d/1-VP4bNkc5kZ3B0yme_vYLiY1qpswnfz8ainnX5fp3l8/[The
Running Fineract.dev, SRE style presentation] given at _ApacheCon 2020_ has
some related background.
diff --git a/fineract-doc/src/docs/en/diagrams/custom-folder-structure.puml
b/fineract-doc/src/docs/en/diagrams/custom-folder-structure.puml
new file mode 100644
index 0000000..bc9b3b5
--- /dev/null
+++ b/fineract-doc/src/docs/en/diagrams/custom-folder-structure.puml
@@ -0,0 +1,17 @@
+@startsalt
+{
+ {T
+ + custom
+ ++ mycustom
+ +++ service
+ ++++ src
+ +++++ main
+ ++++++ java
+ +++++++ org.apache.fineract.mymodule.service
+ ++++++++ MyServiceImpl.java
+ ++++ build.gradle
+ ++++ dependencies.gradle
+ +++ build.gradle
+ }
+}
+@endsalt
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/diagrams/modules-folder-structure.puml
b/fineract-doc/src/docs/en/diagrams/modules-folder-structure.puml
new file mode 100644
index 0000000..f7a61dd
--- /dev/null
+++ b/fineract-doc/src/docs/en/diagrams/modules-folder-structure.puml
@@ -0,0 +1,39 @@
+@startsalt
+{
+ {T
+ + module
+ ++ mymodule
+ +++ core
+ ++++ src
+ +++++ main
+ ++++++ java
+ +++++++ org.apache.fineract.mymodule.core
+ ++++++++ data
+ +++++++++ MyData.java
+ ++++++++ service
+ +++++++++ MyService.java
+ ++++ build.gradle
+ ++++ dependencies.gradle
+ +++ service
+ ++++ src
+ +++++ main
+ ++++++ java
+ +++++++ org.apache.fineract.mymodule.service
+ ++++++++ MyServiceImpl.java
+ ++++ build.gradle
+ ++++ dependencies.gradle
+ +++ starter
+ ++++ src
+ +++++ main
+ ++++++ java
+ +++++++ org.apache.fineract.mymodule.starter
+ ++++++++ MyAutoConfiguration.java
+ ++++ resources
+ +++++ META-INF
+ ++++++ spring.factories
+ ++++ build.gradle
+ ++++ dependencies.gradle
+ +++ build.gradle
+ }
+}
+@endsalt
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/images/apache-fineract-logo.png
b/fineract-doc/src/docs/en/images/apache-fineract-logo.png
new file mode 100644
index 0000000..9b6f470
Binary files /dev/null and
b/fineract-doc/src/docs/en/images/apache-fineract-logo.png differ
diff --git a/fineract-doc/src/docs/en/index.adoc
b/fineract-doc/src/docs/en/index.adoc
index ee07edf..6f32d29 100644
--- a/fineract-doc/src/docs/en/index.adoc
+++ b/fineract-doc/src/docs/en/index.adoc
@@ -4,6 +4,8 @@ include::config.adoc[]
= Fineract Documentation
+include::license.adoc[]
+
include::preface.adoc[]
include::colophon.adoc[]
@@ -14,6 +16,8 @@ include::deployment.adoc[]
include::architecture.adoc[]
+include::modules.adoc[]
+
include::oauth.adoc[]
// include::api.adoc[]
diff --git a/fineract-doc/src/docs/en/license.adoc
b/fineract-doc/src/docs/en/license.adoc
new file mode 100644
index 0000000..9bd9be3
--- /dev/null
+++ b/fineract-doc/src/docs/en/license.adoc
@@ -0,0 +1,15 @@
+== License
+
+Copyright 2022 Apache Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/fineract-doc/src/docs/en/modules.adoc
b/fineract-doc/src/docs/en/modules.adoc
new file mode 100644
index 0000000..f96fc7d8
--- /dev/null
+++ b/fineract-doc/src/docs/en/modules.adoc
@@ -0,0 +1,250 @@
+== Modules
+
+Currently modules are a proof of concept feature in Fineract.
+
+=== How to create a Fineract module
+
+NOTE: At the moment the only module we have that follows these stricter
guidelines is the example module we describe in detail in the next section. In
the future we will try to split up Fineract's monolithic code base and move
features (like loan product, accounts etc.) to separate modules as described
here. Before that happens we need to do some code cleanups first.
+
+1. Create a folder under `module` and name it _mymodule_.
+1. Create a folder named _core_ under `module/mymodule`.
+1. Create a folder named _service_ under `module/mymodule`.
+1. Create a folder named _starter_ under `module/mymodule`.
+1. Setup folders and Gradle build files for a Java project under `core`,
`service` and `starter`.
+1. Create a text file called _spring.factories in folder
`modules/mymodule/starter/src/main/resources/META-INF`.
++
+The final folder and file structure should look somewhat like this:
++
+[plantuml, format=svg]
+----
+include::diagrams/modules-folder-structure.puml[]
+----
+
+1. Make sure that your new modules are present in settings.gradle:
++
+[source,groovy]
+----
+rootProject.name='fineract'
+include ':module:mymodule:core' // <.>
+include ':module:mymodule:service'
+include ':module:mymodule:starter'
+include ':fineract-provider'
+include ':fineract-war'
+include ':integration-tests'
+include ':twofactor-tests'
+include ':oauth2-tests'
+include ':fineract-client'
+include ':fineract-doc'
+----
+<.> The `settings.gradle` file should contain something like this (and
following).
+
+=== How to replace an existing Fineract service
+
+Creating customizations for Fineract services is easy. The method described
here will work both with our future module guidelines (aka "clean room"
modules) and with the intermediary solution we will put in place to avoid major
refactorings.
+
+You can of course choose whatever folder/project structure you like for your
custom modules. But we'll describe here some best practices to avoid merge
conflicts when fetching updates from Fineract's upstream Git repository. For
the time being we suggest to create your custom modules in the same folder as
Fineract in a forked Git repo.
+
+As soon as we can publish Fineract module JARs to Maven Central you'll have
more freedom to setup your projects (including to setup separate Git repos).
+
+1. Create a folder under `custom` and name it _mycustom_.
+1. Create a folder named _service_ under `custom/mycustom`.
+1. Setup folders and Gradle build files for a Java project under `service`.
+1. Create a text file called _spring.factories in folder
`modules/mymodule/starter/src/main/resources/META-INF`:
++
+[source,properties]
+----
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ org.apache.fineract.mymodule.starter.MyAutoConfiguration
+----
++
+The final folder and file structure should look somewhat like this:
++
+[plantuml, format=svg]
+----
+include::diagrams/custom-folder-structure.puml[]
+----
++
+Please make sure that your `service` module's build.gradle file has a unique
group:
++
+[source,groovy]
+----
+description = 'My Company: Fineract My Custom Service'
+
+group = 'com.mycompany.fineract.custom.service' // <.>
+
+apply from: 'dependencies.gradle'
+----
++
+<.> The best choice here is to name it like you would name your JAR artifact
on Maven Central.
+
+1. Make sure that your custom modules are present in settings.gradle: :
++
+[source,groovy]
+----
+rootProject.name='fineract'
+include ':custom:mycustom:service' // <.>
+include ':fineract-provider'
+include ':fineract-war'
+include ':integration-tests'
+include ':twofactor-tests'
+include ':oauth2-tests'
+include ':fineract-client'
+include ':fineract-doc'
+----
+<.> The `settings.gradle` file should contain something like this.
+1. The dependency.gradle file could look something like this:
+[source,groovy]
+----
+dependencies {
+ implementation(project(':module:mymodule:core'), // <.>
+ 'org.springframework:spring-context')
+ compileOnly project(':fineract-provider') // <.>
+}
+----
+<.> If you are replacing a "clean room" module then you just need to include a
dependency on the modules `core` library.
+<.> If you are replacing a service that is not yet extracted from
`fineract-provider` then you need to add a dependency on it (only needed during
compilation).
+1. When the custom module is built then you can add the JAR in your Fineract's
libs folder (or in Tomcat's libs folder if you are deploying as a WAR app).
+
+IMPORTANT: Do not include your custom module in `fineract-provider`'s
dependency.gradle file. This creates a circular dependency and will fail your
build. Instead you have to add your JAR file e. g. to the Docker image (in
Fineract's libs folder; similar like we do it with Pentaho reporting). This
setup will give you the best developer experience for now with proper source
references until we have separate JAR files ready on Maven Central. In the next
section we describe the "clean room" [...]
+
+=== Example
+
+==== Dummy Module Structure
+
+We've created a demonstration how modules are supposed to be used. A module
has usually at least two sub-modules:
+
+1. a _core_ module that contains mostly Java interfaces of the services and/or
other components that we'd like to make replacable. The _core_ module could
also contain data (DTO) or domain (entity) classes if necessary.
+2. a _service_ module
+
+IMPORTANT: Replacing parts of the existing REST API and extending it with
custom endpoints is at the moment out of scope. Probably we'll need to cleanup
and improve the REST layer quite a bit (remove boilerplate code as much as
possible, use Jackson for JSON de-/serialization instead of the manual GSON
mappers/helper everywhere) before this can happen. For now we'll concentrate
primarily on service classes.
+
+Let's assume we have a service `DummyService` in our system. The service is
outlined as a Java interface in module folder `module/dummy/core`.
+
+[source,java]
+----
+include::{rootdir}/module/dummy/core/src/main/java/org/apache/fineract/dummy/core/service/DummyService.java[lines=19..]
+----
+
+To make it a little bit more interesting the service's only function returns a
simple data object that has one string attribute:
+
+[source,java]
+----
+include::{rootdir}/module/dummy/core/src/main/java/org/apache/fineract/dummy/core/data/DummyMessage.java[lines=19..]
+----
+
+A default implementation of `DummyService` is provided with `DummyServiceImpl`:
+
+[source,java]
+----
+include::{rootdir}/module/dummy/service/src/main/java/org/apache/fineract/dummy/service/DummyServiceImpl.java[lines=19..]
+----
+
+As you can see there are no annotations like `@Service` or `@Component`. To
have full control over the instantiation and dependency injection we provide a
so called _starter_ module. This module just contains one or more (auto-)
configuration classes. In this case it's just one configuration class. This is
basically a very simple Spring Java configuration class annotated with
`@Configuration` containing one method that instantiates our default service
implementation (annotated with `@Bean`):
+
+[source,java]
+----
+include::{rootdir}/module/dummy/starter/src/main/java/org/apache/fineract/dummy/starter/DummyAutoConfiguration.java[lines=19..]
+----
+
+The interesting part is this line:
+
+[source,java]
+----
+include::{rootdir}/module/dummy/starter/src/main/java/org/apache/fineract/dummy/starter/DummyAutoConfiguration.java[lines=28..28]
+----
+
+This annotation ensures that our default implementation is only instantiated
if no other implementation for `DummyService` is provided. There's only one
piece missing to make auto configuration work seamlessly and without any
explicit configuration in `fineract-provider`:
+
+[source,properties]
+----
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ org.apache.fineract.dummy.starter.DummyAutoConfiguration
+----
+
+This means if we would only include the following dependencies in our main
project (e. g. `fineract-provider`)...
+
+[source,groovy]
+----
+dependencies {
+ implementation project(':module:dummy:core')
+ implementation project(':module:dummy:service')
+ implementation project(':module:dummy:starter')
+}
+----
+
+\... then the message object would contain
+
+[source,text]
+----
+Hello: DEFAULT DUMMY!
+----
+
+==== Replace the default implementation of DummyService
+
+This is why we created module `foo` in folder `module/foo`. There's only only
one sub-module that contains an implementation of `DummyService` that will
replace the default implementation:
+
+[source,java]
+----
+include::{rootdir}/custom/foo/service/src/main/java/com/acmecorp/fineract/foo/service/FooDummyServiceImpl.java[lines=19..]
+----
+
+As you can see we have no other sub-modules (e. g. there's no starter module)
and this implementation contains the well known `@Service` annotation. If we
add this dependency to our main project...
+
+[source,groovy]
+----
+dependencies {
+ implementation project(':module:dummy:core')
+ implementation project(':module:dummy:service')
+ implementation project(':module:dummy:starter')
+ implementation project(':custom:foo:service')
+}
+----
+
+\... then the expected behavior is that we'll get the message
+
+[source,text]
+----
+Hello: Foo!
+----
+
+==== Testing
+
+There's a simple unit test in `fineract-provider` that demonstrates both
scenarios (without any override of the default implementation and with an
overriding alternative implementation)
+
+[source,gherkin]
+----
+include::{rootdir}/fineract-provider/src/test/resources/features/module/modules.example.feature[]
+----
+
+Here's the Spring Java configuration that does *NOT* load the `foo` module:
+
+[source,java]
+----
+include::{rootdir}/fineract-provider/src/test/java/org/apache/fineract/module/example/TestDefaultConfiguration.java[lines=19..]
+----
+
+\... and here's the configuration that loads the `foo` module (and overrides
the deefault implementation)
+
+[source,java]
+----
+include::{rootdir}/fineract-provider/src/test/java/org/apache/fineract/module/example/TestFooConfiguration.java[lines=19..]
+----
+
+The important part in the `foo` configuration is this line:
+
+[source,java]
+----
+include::{rootdir}/fineract-provider/src/test/java/org/apache/fineract/module/example/TestFooConfiguration.java[lines=26..26]
+----
+
+==== Deployment
+
+Modules (better: the JAR files) only need to be dropped in Fineract's `libs`
folder. Dynamic loading of external JARs is provided since Fineract version
1.5.0.
+
+==== How can I start replacing services now
+
+As said the "clean room" modules will take a while to arrive. In the meanwhile
we'll prepare the existing monolithic code base for pluggability. As a proof of
concept the services
`org.apache.fineract.portfolio.note.service.NoteReadPlatformService` and
`org.apache.fineract.portfolio.note.service.NoteWritePlatformService` can be
replaced/overriden by custom implementations. We'll add more shortly and will
list them here.
+
+==== Outlook
+
+If this proof of concept is accepted we could refactor Fineract's services one
by one and rearrange them in the proposed module structure. As discussed at
ApacheCon 2021 there will be most likely some work to do to properly extract
those modules (loan product, client, savings account etc.) from the monolithic
code base. The main challenge are cross-dependencies between the _modules_, but
there are major benefits if we split up the code like this. One - as
demonstrated - is the replacemen [...]
diff --git a/fineract-provider/dependencies.gradle
b/fineract-provider/dependencies.gradle
index 348f63d..eb19783 100644
--- a/fineract-provider/dependencies.gradle
+++ b/fineract-provider/dependencies.gradle
@@ -135,7 +135,11 @@ dependencies {
'io.cucumber:cucumber-java8',
'io.cucumber:cucumber-junit-platform-engine',
'io.cucumber:cucumber-spring',
- 'io.github.classgraph:classgraph'
+ 'io.github.classgraph:classgraph',
+ project(':module:dummy:core'),
+ project(':module:dummy:service'),
+ project(':module:dummy:starter'),
+ project(':custom:foo:service'),
)
testImplementation ('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'com.jayway.jsonpath', module: 'json-path'
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/boot/ApplicationExitUtil.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/boot/ApplicationExitUtil.java
deleted file mode 100644
index 7406a41..0000000
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/boot/ApplicationExitUtil.java
+++ /dev/null
@@ -1,63 +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.
- */
-package org.apache.fineract.infrastructure.core.boot;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.ConfigurableApplicationContext;
-
-public abstract class ApplicationExitUtil {
-
- private static final Logger LOG =
LoggerFactory.getLogger(ApplicationExitUtil.class);
-
- private ApplicationExitUtil() {}
-
- public static void
waitForKeyPressToCleanlyExit(ConfigurableApplicationContext ctx) throws
IOException {
- // In some environments, System.console() is not available (e.g.
"./gradlew bootRun", or in a container, or in
- // Eclipse, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=122429.
- //
- // Also (but as a separate problem), e.g. in Eclipse, the Shutdown
Hooks are not invoked on Exit with the Red
- // Button of the Console view (see
https://bugs.eclipse.org/bugs/show_bug.cgi?id=38016); that's a problem e.g.
- // in the case of MariaDB4j, because then mysqld won't be stopped;
same problem similarly applies on any other
- // library else that relies on an orderly Spring Context / JVM
shutdown.
- //
- if (System.console() == null) {
- LOG.info("\nNo Console available, running until stopped by
signal/Ctrl-C...");
- boolean interrupted = false;
- do {
- try {
- Thread.sleep(Long.MAX_VALUE);
- } catch (InterruptedException e) {
- interrupted = true;
- }
- } while (!interrupted);
- } else {
- LOG.info("\nHit Enter to quit...");
- BufferedReader d = new BufferedReader(new
InputStreamReader(System.in, StandardCharsets.UTF_8));
- d.readLine();
-
- ctx.stop();
- ctx.close();
- }
- }
-}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/boot/WebFrontEndConfiguration.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/WebFrontEndConfiguration.java
similarity index 97%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/boot/WebFrontEndConfiguration.java
rename to
fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/WebFrontEndConfiguration.java
index 6bea470..7e85d1e 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/boot/WebFrontEndConfiguration.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/WebFrontEndConfiguration.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.infrastructure.core.boot;
+package org.apache.fineract.infrastructure.core.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
index 7c671a5..2041813 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
@@ -133,14 +133,13 @@ import
org.apache.fineract.portfolio.loanproduct.service.LoanDropdownReadPlatfor
import
org.apache.fineract.portfolio.loanproduct.service.LoanProductReadPlatformService;
import org.apache.fineract.portfolio.note.data.NoteData;
import org.apache.fineract.portfolio.note.domain.NoteType;
-import org.apache.fineract.portfolio.note.service.NoteReadPlatformServiceImpl;
+import org.apache.fineract.portfolio.note.service.NoteReadPlatformService;
import org.apache.fineract.portfolio.rate.data.RateData;
import org.apache.fineract.portfolio.rate.service.RateReadService;
import org.apache.fineract.portfolio.savings.DepositAccountType;
import org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@@ -244,7 +243,7 @@ public class LoansApiResource {
private final FromJsonHelper fromJsonHelper;
private final PortfolioCommandSourceWritePlatformService
commandsSourceWritePlatformService;
private final CalendarReadPlatformService calendarReadPlatformService;
- private final NoteReadPlatformServiceImpl noteReadPlatformService;
+ private final NoteReadPlatformService noteReadPlatformService;
private final PortfolioAccountReadPlatformService
portfolioAccountReadPlatformService;
private final AccountAssociationsReadPlatformService
accountAssociationsReadPlatformService;
private final LoanScheduleHistoryReadPlatformService
loanScheduleHistoryReadPlatformService;
@@ -258,7 +257,6 @@ public class LoansApiResource {
private final GLIMAccountInfoReadPlatformService
glimAccountInfoReadPlatformService;
private final LoanCollateralManagementReadPlatformService
loanCollateralManagementReadPlatformService;
- @Autowired
public LoansApiResource(final PlatformSecurityContext context, final
LoanReadPlatformService loanReadPlatformService,
final LoanProductReadPlatformService
loanProductReadPlatformService,
final LoanDropdownReadPlatformService dropdownReadPlatformService,
final FundReadPlatformService fundReadPlatformService,
@@ -272,7 +270,7 @@ public class LoansApiResource {
final DefaultToApiJsonSerializer<LoanScheduleData>
loanScheduleToApiJsonSerializer,
final ApiRequestParameterHelper apiRequestParameterHelper, final
FromJsonHelper fromJsonHelper,
final PortfolioCommandSourceWritePlatformService
commandsSourceWritePlatformService,
- final CalendarReadPlatformService calendarReadPlatformService,
final NoteReadPlatformServiceImpl noteReadPlatformService,
+ final CalendarReadPlatformService calendarReadPlatformService,
final NoteReadPlatformService noteReadPlatformService,
final PortfolioAccountReadPlatformService
portfolioAccountReadPlatformServiceImpl,
final AccountAssociationsReadPlatformService
accountAssociationsReadPlatformService,
final LoanScheduleHistoryReadPlatformService
loanScheduleHistoryReadPlatformService,
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteReadPlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteReadPlatformServiceImpl.java
index fcedec4..377e5fb 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteReadPlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteReadPlatformServiceImpl.java
@@ -32,18 +32,14 @@ import
org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.portfolio.note.data.NoteData;
import org.apache.fineract.portfolio.note.domain.NoteType;
import org.apache.fineract.portfolio.note.exception.NoteNotFoundException;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
-import org.springframework.stereotype.Service;
-@Service
public class NoteReadPlatformServiceImpl implements NoteReadPlatformService {
private final JdbcTemplate jdbcTemplate;
- @Autowired
public NoteReadPlatformServiceImpl(final RoutingDataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java
index 52cdca4..9803356 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteWritePlatformServiceJpaRepositoryImpl.java
@@ -42,10 +42,7 @@ import
org.apache.fineract.portfolio.note.exception.NoteResourceNotSupportedExce
import
org.apache.fineract.portfolio.note.serialization.NoteCommandFromApiJsonDeserializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-@Service
public class NoteWritePlatformServiceJpaRepositoryImpl implements
NoteWritePlatformService {
private static final Logger LOG =
LoggerFactory.getLogger(NoteWritePlatformServiceJpaRepositoryImpl.class);
@@ -56,7 +53,6 @@ public class NoteWritePlatformServiceJpaRepositoryImpl
implements NoteWritePlatf
private final LoanTransactionRepository loanTransactionRepository;
private final NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer;
- @Autowired
public NoteWritePlatformServiceJpaRepositoryImpl(final NoteRepository
noteRepository, final ClientRepositoryWrapper clientRepository,
final GroupRepository groupRepository, final LoanRepositoryWrapper
loanRepository,
final LoanTransactionRepository loanTransactionRepository, final
NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer) {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/starter/NoteAutoConfiguration.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/starter/NoteAutoConfiguration.java
new file mode 100644
index 0000000..1bea6c8
--- /dev/null
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/starter/NoteAutoConfiguration.java
@@ -0,0 +1,53 @@
+/**
+ * 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.
+ */
+package org.apache.fineract.portfolio.note.starter;
+
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
+import org.apache.fineract.portfolio.group.domain.GroupRepository;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
+import
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
+import org.apache.fineract.portfolio.note.domain.NoteRepository;
+import
org.apache.fineract.portfolio.note.serialization.NoteCommandFromApiJsonDeserializer;
+import org.apache.fineract.portfolio.note.service.NoteReadPlatformService;
+import org.apache.fineract.portfolio.note.service.NoteReadPlatformServiceImpl;
+import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
+import
org.apache.fineract.portfolio.note.service.NoteWritePlatformServiceJpaRepositoryImpl;
+import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class NoteAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public NoteReadPlatformService noteReadPlatformService(RoutingDataSource
routingDataSource) {
+ return new NoteReadPlatformServiceImpl(routingDataSource);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public NoteWritePlatformService noteWritePlatformService(NoteRepository
noteRepository, ClientRepositoryWrapper clientRepository,
+ GroupRepository groupRepository, LoanRepositoryWrapper
loanRepository, LoanTransactionRepository loanTransactionRepository,
+ NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer) {
+ return new NoteWritePlatformServiceJpaRepositoryImpl(noteRepository,
clientRepository, groupRepository, loanRepository,
+ loanTransactionRepository, fromApiJsonDeserializer);
+ }
+}
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 39a3e35..9ef2543 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/TestConfiguration.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/TestConfiguration.java
@@ -22,7 +22,6 @@ import static org.mockito.Mockito.mock;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
-import
org.apache.fineract.infrastructure.core.boot.AbstractApplicationConfiguration;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import
org.apache.fineract.infrastructure.core.service.database.DatabaseIndependentQueryService;
@@ -37,19 +36,37 @@ import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
+import
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
+import
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
+import
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import
org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import
org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* Spring @Configuration which does not require a running database. It also
does not load any job configuration (as they
* are in the DB), thus nor starts any background jobs. For some integration
tests, this may be perfectly sufficient
* (and faster to run such tests).
*/
-@EnableConfigurationProperties({ FineractProperties.class })
+@Configuration
+@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class,
+ DataSourceTransactionManagerAutoConfiguration.class,
GsonAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
+ LiquibaseAutoConfiguration.class })
+@EnableTransactionManagement
+@EnableWebSecurity
+@EnableConfigurationProperties({ FineractProperties.class,
LiquibaseProperties.class })
+@ComponentScan(basePackages = "org.apache.fineract")
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
-public class TestConfiguration extends AbstractApplicationConfiguration {
+public class TestConfiguration {
@Bean
public TenantDataSourceFactory tenantDataSourceFactory() {
diff --git
a/fineract-provider/src/test/java/org/apache/fineract/module/example/DummyServiceStepDefinitions.java
b/fineract-provider/src/test/java/org/apache/fineract/module/example/DummyServiceStepDefinitions.java
new file mode 100644
index 0000000..ccbacd7
--- /dev/null
+++
b/fineract-provider/src/test/java/org/apache/fineract/module/example/DummyServiceStepDefinitions.java
@@ -0,0 +1,54 @@
+/**
+ * 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.
+ */
+package org.apache.fineract.module.example;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.cucumber.java8.En;
+import org.apache.fineract.dummy.core.data.DummyMessage;
+import org.apache.fineract.dummy.core.service.DummyService;
+import org.apache.fineract.dummy.starter.DummyAutoConfiguration;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+
+public class DummyServiceStepDefinitions implements En {
+
+ private DummyMessage message;
+
+ private ApplicationContextRunner contextRunner = new
ApplicationContextRunner()
+
.withConfiguration(AutoConfigurations.of(DummyAutoConfiguration.class));
+
+ public DummyServiceStepDefinitions() {
+ Given("/^A dummy service configuration (.*)$/", (String
configurationClass) -> {
+ contextRunner =
contextRunner.withUserConfiguration(Class.forName(configurationClass.trim()));
+ });
+
+ When("The user gets the dummy service message", () -> {
+ contextRunner.run((ctx) -> {
+ assertThat(ctx).hasSingleBean(DummyService.class);
+ this.message = ctx.getBean(DummyService.class).getMessage();
+ });
+ });
+
+ Then("/^The dummy service message should match (.*)$/", (String msg)
-> {
+ assertThat(this.message).isNotNull();
+ assertThat(msg).isEqualTo(this.message.getMessage());
+ });
+ }
+}
diff --git a/settings.gradle
b/fineract-provider/src/test/java/org/apache/fineract/module/example/TestDefaultConfiguration.java
similarity index 72%
copy from settings.gradle
copy to
fineract-provider/src/test/java/org/apache/fineract/module/example/TestDefaultConfiguration.java
index 0a304eb..6978660 100644
--- a/settings.gradle
+++
b/fineract-provider/src/test/java/org/apache/fineract/module/example/TestDefaultConfiguration.java
@@ -16,11 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+package org.apache.fineract.module.example;
+
+import org.apache.fineract.infrastructure.core.config.FineractProperties;
+import
org.springframework.boot.context.properties.EnableConfigurationProperties;
+
+@EnableConfigurationProperties({ FineractProperties.class })
+public class TestDefaultConfiguration {}
diff --git a/settings.gradle
b/fineract-provider/src/test/java/org/apache/fineract/module/example/TestFooConfiguration.java
similarity index 66%
copy from settings.gradle
copy to
fineract-provider/src/test/java/org/apache/fineract/module/example/TestFooConfiguration.java
index 0a304eb..c22bf63 100644
--- a/settings.gradle
+++
b/fineract-provider/src/test/java/org/apache/fineract/module/example/TestFooConfiguration.java
@@ -16,11 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+package org.apache.fineract.module.example;
+
+import org.apache.fineract.infrastructure.core.config.FineractProperties;
+import
org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.ComponentScan;
+
+@EnableConfigurationProperties({ FineractProperties.class })
+@ComponentScan("com.acmecorp.fineract.foo")
+public class TestFooConfiguration {}
diff --git
a/fineract-provider/src/test/java/org/apache/fineract/module/service/ServiceStepDefinitions.java
b/fineract-provider/src/test/java/org/apache/fineract/module/service/ServiceStepDefinitions.java
new file mode 100644
index 0000000..1759097
--- /dev/null
+++
b/fineract-provider/src/test/java/org/apache/fineract/module/service/ServiceStepDefinitions.java
@@ -0,0 +1,58 @@
+/**
+ * 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.
+ */
+package org.apache.fineract.module.service;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.cucumber.java8.En;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+
+public class ServiceStepDefinitions implements En {
+
+ private Class interfaceClass;
+
+ private Class implementationClass;
+
+ private ApplicationContextRunner contextRunner;
+
+ public ServiceStepDefinitions() {
+ Given("/^An auto configuration (.*) and a service configuration
(.*)$/",
+ (String autoConfigurationClassName, String
configurationClassName) -> {
+ contextRunner = new ApplicationContextRunner()
+
.withConfiguration(AutoConfigurations.of(Class.forName(autoConfigurationClassName)))
+
.withUserConfiguration(Class.forName(configurationClassName.trim()));
+ });
+
+ When("/^The user retrieves the service of interface class (.*)$/",
(String interfaceClassName) -> {
+ contextRunner.run((ctx) -> {
+ this.interfaceClass = Class.forName(interfaceClassName.trim());
+
+ assertThat(this.interfaceClass.isInterface()).isTrue();
+ assertThat(ctx).hasSingleBean(this.interfaceClass);
+
+ this.implementationClass =
ctx.getBean(interfaceClass).getClass();
+ });
+ });
+
+ Then("/^The service class should match (.*)$/", (String
serviceClassName) -> {
+
assertThat(Class.forName(serviceClassName.trim())).isEqualTo(this.implementationClass);
+ });
+ }
+}
diff --git
a/fineract-provider/src/test/java/org/apache/fineract/module/service/TestDefaultConfiguration.java
b/fineract-provider/src/test/java/org/apache/fineract/module/service/TestDefaultConfiguration.java
new file mode 100644
index 0000000..5f1bd24
--- /dev/null
+++
b/fineract-provider/src/test/java/org/apache/fineract/module/service/TestDefaultConfiguration.java
@@ -0,0 +1,84 @@
+/**
+ * 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.
+ */
+package org.apache.fineract.module.service;
+
+import static org.mockito.Mockito.mock;
+
+import org.apache.fineract.infrastructure.core.config.FineractProperties;
+import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import
org.apache.fineract.infrastructure.core.service.RoutingDataSourceServiceFactory;
+import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
+import org.apache.fineract.portfolio.group.domain.GroupRepository;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
+import
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
+import org.apache.fineract.portfolio.note.domain.NoteRepository;
+import
org.apache.fineract.portfolio.note.serialization.NoteCommandFromApiJsonDeserializer;
+import
org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+
+@EnableConfigurationProperties({ FineractProperties.class })
+public class TestDefaultConfiguration {
+ // NOTE: unfortunately an abastract base class that contains all these
mock functions won't work
+
+ @Bean
+ public FromJsonHelper fromJsonHelper() {
+ return mock(FromJsonHelper.class);
+ }
+
+ @Bean
+ public RoutingDataSourceServiceFactory routingDataSourceServiceFactory() {
+ return mock(RoutingDataSourceServiceFactory.class);
+ }
+
+ @Bean
+ public RoutingDataSource routingDataSource() {
+ return mock(RoutingDataSource.class);
+ }
+
+ @Bean
+ public NoteRepository noteRepository() {
+ return mock(NoteRepository.class);
+ }
+
+ @Bean
+ public ClientRepositoryWrapper clientRepository() {
+ return mock(ClientRepositoryWrapper.class);
+ }
+
+ @Bean
+ public GroupRepository groupRepository() {
+ return mock(GroupRepository.class);
+ }
+
+ @Bean
+ public LoanRepositoryWrapper loanRepository() {
+ return mock(LoanRepositoryWrapper.class);
+ }
+
+ @Bean
+ public LoanTransactionRepository loanTransactionRepository() {
+ return mock(LoanTransactionRepository.class);
+ }
+
+ @Bean
+ public NoteCommandFromApiJsonDeserializer
fromApiJsonDeserializer(FromJsonHelper fromJsonHelper) {
+ return new NoteCommandFromApiJsonDeserializer(fromJsonHelper);
+ }
+}
diff --git
a/fineract-provider/src/test/java/org/apache/fineract/module/service/TestOverrideConfiguration.java
b/fineract-provider/src/test/java/org/apache/fineract/module/service/TestOverrideConfiguration.java
new file mode 100644
index 0000000..dfc0544
--- /dev/null
+++
b/fineract-provider/src/test/java/org/apache/fineract/module/service/TestOverrideConfiguration.java
@@ -0,0 +1,83 @@
+/**
+ * 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.
+ */
+package org.apache.fineract.module.service;
+
+import static org.mockito.Mockito.mock;
+
+import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import
org.apache.fineract.infrastructure.core.service.RoutingDataSourceServiceFactory;
+import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
+import org.apache.fineract.portfolio.group.domain.GroupRepository;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
+import
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
+import org.apache.fineract.portfolio.note.domain.NoteRepository;
+import
org.apache.fineract.portfolio.note.serialization.NoteCommandFromApiJsonDeserializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+
+@ComponentScan("org.apache.fineract.module.service.custom")
+public class TestOverrideConfiguration {
+ // NOTE: unfortunately an abastract base class that contains all these
mock functions won't work
+
+ @Bean
+ public FromJsonHelper fromJsonHelper() {
+ return mock(FromJsonHelper.class);
+ }
+
+ @Bean
+ public RoutingDataSourceServiceFactory routingDataSourceServiceFactory() {
+ return mock(RoutingDataSourceServiceFactory.class);
+ }
+
+ @Bean
+ public RoutingDataSource routingDataSource() {
+ return mock(RoutingDataSource.class);
+ }
+
+ @Bean
+ public NoteRepository noteRepository() {
+ return mock(NoteRepository.class);
+ }
+
+ @Bean
+ public ClientRepositoryWrapper clientRepository() {
+ return mock(ClientRepositoryWrapper.class);
+ }
+
+ @Bean
+ public GroupRepository groupRepository() {
+ return mock(GroupRepository.class);
+ }
+
+ @Bean
+ public LoanRepositoryWrapper loanRepository() {
+ return mock(LoanRepositoryWrapper.class);
+ }
+
+ @Bean
+ public LoanTransactionRepository loanTransactionRepository() {
+ return mock(LoanTransactionRepository.class);
+ }
+
+ @Bean
+ public NoteCommandFromApiJsonDeserializer
fromApiJsonDeserializer(FromJsonHelper fromJsonHelper) {
+ return new NoteCommandFromApiJsonDeserializer(fromJsonHelper);
+ }
+}
diff --git a/settings.gradle
b/fineract-provider/src/test/java/org/apache/fineract/module/service/custom/CustomNoteReadPlatformService.java
similarity index 56%
copy from settings.gradle
copy to
fineract-provider/src/test/java/org/apache/fineract/module/service/custom/CustomNoteReadPlatformService.java
index 0a304eb..7d4e5c0 100644
--- a/settings.gradle
+++
b/fineract-provider/src/test/java/org/apache/fineract/module/service/custom/CustomNoteReadPlatformService.java
@@ -16,11 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+package org.apache.fineract.module.service.custom;
+
+import java.util.Collection;
+import org.apache.fineract.portfolio.note.data.NoteData;
+import org.apache.fineract.portfolio.note.service.NoteReadPlatformService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class CustomNoteReadPlatformService implements NoteReadPlatformService {
+
+ @Override
+ public NoteData retrieveNote(Long noteId, Long resourceId, Integer
noteTypeId) {
+ return null;
+ }
+
+ @Override
+ public Collection<NoteData> retrieveNotesByResource(Long resourceId,
Integer noteTypeId) {
+ return null;
+ }
+}
diff --git
a/fineract-provider/src/test/java/org/apache/fineract/module/service/custom/CustomNoteWritePlatformService.java
b/fineract-provider/src/test/java/org/apache/fineract/module/service/custom/CustomNoteWritePlatformService.java
new file mode 100644
index 0000000..ecc82db
--- /dev/null
+++
b/fineract-provider/src/test/java/org/apache/fineract/module/service/custom/CustomNoteWritePlatformService.java
@@ -0,0 +1,49 @@
+/**
+ * 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.
+ */
+package org.apache.fineract.module.service.custom;
+
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.portfolio.client.domain.Client;
+import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class CustomNoteWritePlatformService implements
NoteWritePlatformService {
+
+ @Override
+ public CommandProcessingResult createNote(JsonCommand command) {
+ return null;
+ }
+
+ @Override
+ public CommandProcessingResult updateNote(JsonCommand command) {
+ return null;
+ }
+
+ @Override
+ public CommandProcessingResult deleteNote(JsonCommand command) {
+ return null;
+ }
+
+ @Override
+ public void createAndPersistClientNote(Client client, JsonCommand command)
{
+
+ }
+}
diff --git a/fineract-provider/src/test/resources/cucumber.properties
b/fineract-provider/src/test/resources/cucumber.properties
index d3b2786..a745f74 100644
--- a/fineract-provider/src/test/resources/cucumber.properties
+++ b/fineract-provider/src/test/resources/cucumber.properties
@@ -18,3 +18,4 @@
#
cucumber.publish.quiet=true
+cucumber.glue=org.apache.fineract
diff --git
a/fineract-provider/src/test/resources/features/module/modules.example.feature
b/fineract-provider/src/test/resources/features/module/modules.example.feature
new file mode 100644
index 0000000..ad2be04
--- /dev/null
+++
b/fineract-provider/src/test/resources/features/module/modules.example.feature
@@ -0,0 +1,12 @@
+Feature: Example Modules
+
+ @modules
+ Scenario Outline: Verify that the dummy service returns the correct message
+ Given A dummy service configuration <configurationClass>
+ When The user gets the dummy service message
+ Then The dummy service message should match <message>
+
+ Examples:
+ | configurationClass | message
|
+ | org.apache.fineract.module.example.TestDefaultConfiguration | Hello:
DEFAULT DUMMY! |
+ | org.apache.fineract.module.example.TestFooConfiguration | Hello:
FOO! |
\ No newline at end of file
diff --git
a/fineract-provider/src/test/resources/features/module/modules.service.feature
b/fineract-provider/src/test/resources/features/module/modules.service.feature
new file mode 100644
index 0000000..6aee6ba
--- /dev/null
+++
b/fineract-provider/src/test/resources/features/module/modules.service.feature
@@ -0,0 +1,14 @@
+Feature: Service Modules
+
+ @modules
+ Scenario Outline: Verify that the dummy service returns the correct message
+ Given An auto configuration <autoConfigurationClass> and a service
configuration <configurationClass>
+ When The user retrieves the service of interface class <interfaceClass>
+ Then The service class should match <serviceClass>
+
+ Examples:
+ | autoConfigurationClass |
configurationClass | interfaceClass
| serviceClass
|
+ | org.apache.fineract.portfolio.note.starter.NoteAutoConfiguration |
org.apache.fineract.module.service.TestDefaultConfiguration |
org.apache.fineract.portfolio.note.service.NoteReadPlatformService |
org.apache.fineract.portfolio.note.service.NoteReadPlatformServiceImpl
|
+ | org.apache.fineract.portfolio.note.starter.NoteAutoConfiguration |
org.apache.fineract.module.service.TestDefaultConfiguration |
org.apache.fineract.portfolio.note.service.NoteWritePlatformService |
org.apache.fineract.portfolio.note.service.NoteWritePlatformServiceJpaRepositoryImpl
|
+ | org.apache.fineract.portfolio.note.starter.NoteAutoConfiguration |
org.apache.fineract.module.service.TestOverrideConfiguration |
org.apache.fineract.portfolio.note.service.NoteReadPlatformService |
org.apache.fineract.module.service.custom.CustomNoteReadPlatformService
|
+ | org.apache.fineract.portfolio.note.starter.NoteAutoConfiguration |
org.apache.fineract.module.service.TestOverrideConfiguration |
org.apache.fineract.portfolio.note.service.NoteWritePlatformService |
org.apache.fineract.module.service.custom.CustomNoteWritePlatformService
|
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 11fe8a7..89f430e 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -16,6 +16,6 @@
# specific language governing permissions and limitations
# under the License.
#
-org.gradle.jvmargs=-Xmx2g --add-exports
jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports
jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED --add-exports
jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED --add-exports
jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-exports
jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
--add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.lang.invoke=ALL-UN [...]
+org.gradle.jvmargs=-Xmx2g --add-exports
jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports
jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED --add-exports
jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED --add-exports
jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-exports
jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
--add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.lang.invoke=ALL-UN [...]
buildType=BUILD
org.gradle.caching=true
diff --git a/integration-tests/build.gradle b/integration-tests/build.gradle
index f395cf9..1217e8e 100644
--- a/integration-tests/build.gradle
+++ b/integration-tests/build.gradle
@@ -28,6 +28,9 @@ configurations {
apply from: 'dependencies.gradle'
+// enable when all tests are migrated
+tasks.cucumber.onlyIf {false}
+
cargo {
containerId "tomcat9x"
@@ -39,6 +42,7 @@ cargo {
local {
logLevel = 'medium'
+ // outputFile = file('build/output.log')
installer {
installConfiguration = configurations.tomcat
downloadDir = file("$buildDir/download")
diff --git a/integration-tests/src/test/resources/cucumber.properties
b/integration-tests/src/test/resources/cucumber.properties
index d3b2786..a745f74 100644
--- a/integration-tests/src/test/resources/cucumber.properties
+++ b/integration-tests/src/test/resources/cucumber.properties
@@ -18,3 +18,4 @@
#
cucumber.publish.quiet=true
+cucumber.glue=org.apache.fineract
diff --git a/settings.gradle b/module/build.gradle
similarity index 79%
copy from settings.gradle
copy to module/build.gradle
index 0a304eb..d145498 100644
--- a/settings.gradle
+++ b/module/build.gradle
@@ -16,11 +16,4 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+description = 'Fineract Module'
diff --git a/settings.gradle b/module/dummy/build.gradle
similarity index 79%
copy from settings.gradle
copy to module/dummy/build.gradle
index 0a304eb..016d5b2 100644
--- a/settings.gradle
+++ b/module/dummy/build.gradle
@@ -16,11 +16,4 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+description = 'Fineract Module: Dummy'
diff --git a/settings.gradle b/module/dummy/core/build.gradle
similarity index 79%
copy from settings.gradle
copy to module/dummy/core/build.gradle
index 0a304eb..bd83b90 100644
--- a/settings.gradle
+++ b/module/dummy/core/build.gradle
@@ -16,11 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+description = 'Fineract Module: Dummy Core'
+
+group = 'org.apache.fineract.dummy.core'
+
+apply from: 'dependencies.gradle'
diff --git a/settings.gradle b/module/dummy/core/dependencies.gradle
similarity index 79%
copy from settings.gradle
copy to module/dummy/core/dependencies.gradle
index 0a304eb..e819cc7 100644
--- a/settings.gradle
+++ b/module/dummy/core/dependencies.gradle
@@ -16,11 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+
+dependencies {
+ implementation('org.springframework:spring-context')
+}
diff --git a/settings.gradle
b/module/dummy/core/src/main/java/org/apache/fineract/dummy/core/data/DummyMessage.java
similarity index 70%
copy from settings.gradle
copy to
module/dummy/core/src/main/java/org/apache/fineract/dummy/core/data/DummyMessage.java
index 0a304eb..67e4350 100644
--- a/settings.gradle
+++
b/module/dummy/core/src/main/java/org/apache/fineract/dummy/core/data/DummyMessage.java
@@ -16,11 +16,20 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+package org.apache.fineract.dummy.core.data;
+
+public class DummyMessage {
+ private String message;
+
+ public DummyMessage(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
diff --git a/settings.gradle
b/module/dummy/core/src/main/java/org/apache/fineract/dummy/core/service/DummyService.java
similarity index 79%
copy from settings.gradle
copy to
module/dummy/core/src/main/java/org/apache/fineract/dummy/core/service/DummyService.java
index 0a304eb..f0ae2a6 100644
--- a/settings.gradle
+++
b/module/dummy/core/src/main/java/org/apache/fineract/dummy/core/service/DummyService.java
@@ -16,11 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+package org.apache.fineract.dummy.core.service;
+
+import org.apache.fineract.dummy.core.data.DummyMessage;
+
+public interface DummyService {
+ DummyMessage getMessage();
+}
diff --git a/settings.gradle b/module/dummy/service/build.gradle
similarity index 79%
copy from settings.gradle
copy to module/dummy/service/build.gradle
index 0a304eb..8e59db8 100644
--- a/settings.gradle
+++ b/module/dummy/service/build.gradle
@@ -16,11 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+description = 'Fineract Module: Dummy Service'
+
+group = 'org.apache.fineract.dummy.service'
+
+apply from: 'dependencies.gradle'
diff --git a/settings.gradle b/module/dummy/service/dependencies.gradle
similarity index 79%
copy from settings.gradle
copy to module/dummy/service/dependencies.gradle
index 0a304eb..517ab7d 100644
--- a/settings.gradle
+++ b/module/dummy/service/dependencies.gradle
@@ -16,11 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+
+dependencies {
+ implementation(project(':module:dummy:core'),
+ 'org.springframework:spring-context')
+}
diff --git a/settings.gradle
b/module/dummy/service/src/main/java/org/apache/fineract/dummy/service/DummyServiceImpl.java
similarity index 70%
copy from settings.gradle
copy to
module/dummy/service/src/main/java/org/apache/fineract/dummy/service/DummyServiceImpl.java
index 0a304eb..02eb36d 100644
--- a/settings.gradle
+++
b/module/dummy/service/src/main/java/org/apache/fineract/dummy/service/DummyServiceImpl.java
@@ -16,11 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+package org.apache.fineract.dummy.service;
+
+import org.apache.fineract.dummy.core.data.DummyMessage;
+import org.apache.fineract.dummy.core.service.DummyService;
+
+public class DummyServiceImpl implements DummyService {
+ @Override
+ public DummyMessage getMessage() {
+ return new DummyMessage("Hello: DEFAULT DUMMY!");
+ }
+}
diff --git a/settings.gradle b/module/dummy/starter/build.gradle
similarity index 79%
copy from settings.gradle
copy to module/dummy/starter/build.gradle
index 0a304eb..ab64be9 100644
--- a/settings.gradle
+++ b/module/dummy/starter/build.gradle
@@ -16,11 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+description = 'Fineract Module: Dummy Starter'
+
+group = 'org.apache.fineract.dummy.starter'
+
+apply from: 'dependencies.gradle'
diff --git a/settings.gradle b/module/dummy/starter/dependencies.gradle
similarity index 79%
copy from settings.gradle
copy to module/dummy/starter/dependencies.gradle
index 0a304eb..4c8348e 100644
--- a/settings.gradle
+++ b/module/dummy/starter/dependencies.gradle
@@ -16,11 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+
+dependencies {
+ implementation(project(':module:dummy:core'),
+ project(':module:dummy:service'),
+ 'org.springframework.boot:spring-boot-starter')
+}
diff --git a/settings.gradle
b/module/dummy/starter/src/main/java/org/apache/fineract/dummy/starter/DummyAutoConfiguration.java
similarity index 59%
copy from settings.gradle
copy to
module/dummy/starter/src/main/java/org/apache/fineract/dummy/starter/DummyAutoConfiguration.java
index 0a304eb..1dc7427 100644
--- a/settings.gradle
+++
b/module/dummy/starter/src/main/java/org/apache/fineract/dummy/starter/DummyAutoConfiguration.java
@@ -16,11 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
-rootProject.name='fineract'
-include ':fineract-provider'
-include ':fineract-war'
-include ':integration-tests'
-include ':twofactor-tests'
-include ':oauth2-tests'
-include ':fineract-client'
-include ':fineract-doc'
+package org.apache.fineract.dummy.starter;
+
+import org.apache.fineract.dummy.core.service.DummyService;
+import org.apache.fineract.dummy.service.DummyServiceImpl;
+import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConditionalOnMissingBean(DummyService.class)
+public class DummyAutoConfiguration {
+ @Bean
+ public DummyService dummyService() {
+ return new DummyServiceImpl();
+ }
+}
diff --git a/module/dummy/starter/src/main/resources/META-INF/spring.factories
b/module/dummy/starter/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..5dcbd56
--- /dev/null
+++ b/module/dummy/starter/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+org.apache.fineract.dummy.starter.DummyAutoConfiguration
\ No newline at end of file
diff --git a/oauth2-tests/build.gradle b/oauth2-tests/build.gradle
index 1a89ab7..eebd32d 100644
--- a/oauth2-tests/build.gradle
+++ b/oauth2-tests/build.gradle
@@ -28,6 +28,9 @@ configurations {
apply from: 'dependencies.gradle'
+// enable when all tests are migrated
+tasks.cucumber.onlyIf {false}
+
cargo {
containerId "tomcat9x"
@@ -38,6 +41,8 @@ cargo {
}
local {
+ // logLevel = 'medium'
+ // outputFile = file('build/output.log')
installer {
installConfiguration = configurations.tomcat
downloadDir = file("$buildDir/download")
diff --git a/oauth2-tests/dependencies.gradle b/oauth2-tests/dependencies.gradle
index e8088f6..dc085d4 100644
--- a/oauth2-tests/dependencies.gradle
+++ b/oauth2-tests/dependencies.gradle
@@ -26,12 +26,6 @@ dependencies {
'org.junit.jupiter:junit-jupiter-api',
'org.bouncycastle:bcpkix-jdk15to18',
'org.bouncycastle:bcprov-jdk15to18',
- 'io.cucumber:cucumber-core',
- 'io.cucumber:cucumber-java',
- 'io.cucumber:cucumber-java8',
- 'io.cucumber:cucumber-junit-platform-engine',
- 'io.cucumber:cucumber-spring',
- 'com.intuit.karate:karate-junit5',
)
testImplementation ('io.rest-assured:rest-assured') {
exclude group: 'commons-logging'
diff --git a/fineract-client/src/test/resources/cucumber.properties
b/oauth2-tests/src/test/resources/cucumber.properties
similarity index 95%
copy from fineract-client/src/test/resources/cucumber.properties
copy to oauth2-tests/src/test/resources/cucumber.properties
index d3b2786..a745f74 100644
--- a/fineract-client/src/test/resources/cucumber.properties
+++ b/oauth2-tests/src/test/resources/cucumber.properties
@@ -18,3 +18,4 @@
#
cucumber.publish.quiet=true
+cucumber.glue=org.apache.fineract
diff --git a/settings.gradle b/settings.gradle
index 0a304eb..4fb8b3b 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -17,6 +17,10 @@
* under the License.
*/
rootProject.name='fineract'
+include ':module:dummy:core'
+include ':module:dummy:service'
+include ':module:dummy:starter'
+include ':custom:foo:service'
include ':fineract-provider'
include ':fineract-war'
include ':integration-tests'
diff --git a/twofactor-tests/build.gradle b/twofactor-tests/build.gradle
index a83febb..272fa0f 100644
--- a/twofactor-tests/build.gradle
+++ b/twofactor-tests/build.gradle
@@ -28,6 +28,9 @@ configurations {
apply from: 'dependencies.gradle'
+// enable when all tests are migrated
+tasks.cucumber.onlyIf {false}
+
cargo {
containerId "tomcat9x"
@@ -38,6 +41,8 @@ cargo {
}
local {
+ // logLevel = 'medium'
+ // outputFile = file('build/output.log')
installer {
installConfiguration = configurations.tomcat
downloadDir = file("$buildDir/download")
diff --git a/twofactor-tests/dependencies.gradle
b/twofactor-tests/dependencies.gradle
index 190bfff..85cb0c6 100644
--- a/twofactor-tests/dependencies.gradle
+++ b/twofactor-tests/dependencies.gradle
@@ -24,15 +24,9 @@ dependencies {
testImplementation(
files("$rootDir/fineract-provider/build/classes/java/main/"),
project(path: ':fineract-provider', configuration:
'runtimeElements'),
'org.junit.jupiter:junit-jupiter-api',
+ 'com.icegreen:greenmail-junit5',
'org.bouncycastle:bcpkix-jdk15to18',
'org.bouncycastle:bcprov-jdk15to18',
- 'io.cucumber:cucumber-core',
- 'io.cucumber:cucumber-java',
- 'io.cucumber:cucumber-java8',
- 'io.cucumber:cucumber-junit-platform-engine',
- 'io.cucumber:cucumber-spring',
- 'com.icegreen:greenmail-junit5',
- 'com.intuit.karate:karate-junit5',
)
testImplementation ('io.rest-assured:rest-assured') {
exclude group: 'commons-logging'
diff --git a/fineract-client/src/test/resources/cucumber.properties
b/twofactor-tests/src/test/resources/cucumber.properties
similarity index 95%
copy from fineract-client/src/test/resources/cucumber.properties
copy to twofactor-tests/src/test/resources/cucumber.properties
index d3b2786..a745f74 100644
--- a/fineract-client/src/test/resources/cucumber.properties
+++ b/twofactor-tests/src/test/resources/cucumber.properties
@@ -18,3 +18,4 @@
#
cucumber.publish.quiet=true
+cucumber.glue=org.apache.fineract