You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by pt...@apache.org on 2021/12/23 14:21:45 UTC
[fineract] 01/01: Idempotency Support (FINERACT-1420)
This is an automated email from the ASF dual-hosted git repository.
ptuomola pushed a commit to branch idempotency
in repository https://gitbox.apache.org/repos/asf/fineract.git
commit d6b40d436d498b895623ac99ccbf3f5d43793105
Author: Vic Romero <vi...@fintecheando.mx>
AuthorDate: Mon Nov 1 23:29:08 2021 -0600
Idempotency Support (FINERACT-1420)
---
build.gradle | 2 +
docker-compose-idempotent.yml | 128 +++++++++++++++++++++
fineract-provider/dependencies.gradle | 2 +
.../properties/basicauth/application.properties | 15 +++
.../savings/api/SavingsProductsApiResource.java | 8 +-
.../src/main/resources/logback-spring.xml | 1 +
6 files changed, 155 insertions(+), 1 deletion(-)
diff --git a/build.gradle b/build.gradle
index aa550fa..38e0d3f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -174,6 +174,8 @@ allprojects {
dependency "javax.annotation:javax.annotation-api:1.3.2"
dependency "com.google.code.findbugs:jsr305:3.0.2"
dependency "commons-codec:commons-codec:1.15"
+ //Idempotency Library
+ dependency "com.trendyol:Jdempotent-spring-boot-redis-starter:1.0.10"
dependency ('org.flywaydb:flyway-core:7.15.0') {
// https://issues.apache.org/jira/browse/FINERACT-1172
diff --git a/docker-compose-idempotent.yml b/docker-compose-idempotent.yml
new file mode 100644
index 0000000..29a5eb0
--- /dev/null
+++ b/docker-compose-idempotent.yml
@@ -0,0 +1,128 @@
+# 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.
+#
+
+# NB: Travis CI (dist: bionic) supports up to v3.7
+# (unless we'd install a more recent version in .travis.yml)
+version: '3.7'
+networks:
+ app-tier:
+ driver: bridge
+services:
+ redis:
+ image: 'bitnami/redis:latest'
+ environment:
+ - REDIS_REPLICATION_MODE=master
+ - REDIS_PASSWORD=str0ng_passw0rd
+ networks:
+ - app-tier
+ ports:
+ - '6379:6379'
+ redis-slave:
+ image: 'bitnami/redis:latest'
+ environment:
+ - REDIS_REPLICATION_MODE=slave
+ - REDIS_MASTER_HOST=redis
+ - REDIS_MASTER_PASSWORD=str0ng_passw0rd
+ - REDIS_PASSWORD=str0ng_passw0rd
+ ports:
+ - '6379'
+ depends_on:
+ - redis
+ networks:
+ - app-tier
+ redis-slave-2:
+ image: 'bitnami/redis:latest'
+ environment:
+ - REDIS_REPLICATION_MODE=slave
+ - REDIS_MASTER_HOST=redis
+ - REDIS_MASTER_PASSWORD=str0ng_passw0rd
+ - REDIS_PASSWORD=str0ng_passw0rd
+ ports:
+ - '6379'
+ depends_on:
+ - redis
+ networks:
+ - app-tier
+ redis-sentinel:
+ image: 'bitnami/redis-sentinel:latest'
+ environment:
+ - REDIS_MASTER_PASSWORD=str0ng_passw0rd
+ depends_on:
+ - redis
+ - redis-slave
+ - redis-slave-2
+ ports:
+ - '26379:26379'
+ networks:
+ - app-tier
+ # Backend service
+ fineractmysql:
+ image: mysql:5.7
+ volumes:
+ - ./fineract-db/docker:/docker-entrypoint-initdb.d:Z,ro
+ restart: always
+ environment:
+ MYSQL_ROOT_PASSWORD: skdcnwauicn2ucnaecasdsajdnizucawencascdca
+ healthcheck:
+ test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "--password=skdcnwauicn2ucnaecasdsajdnizucawencascdca" ]
+ timeout: 10s
+ retries: 10
+ ports:
+ - "3306:3306"
+ networks:
+ - app-tier
+ fineract-server:
+ build:
+ context: .
+ target: fineract
+ ports:
+ - 8443:8443
+ networks:
+ - app-tier
+ depends_on:
+ - fineractmysql
+ environment:
+ - DRIVERCLASS_NAME=org.drizzle.jdbc.DrizzleDriver
+ - PROTOCOL=jdbc
+ - node_id=1
+ - SUB_PROTOCOL=mysql:thin
+ - fineract_tenants_driver=org.drizzle.jdbc.DrizzleDriver
+ - fineract_tenants_url=jdbc:mysql:thin://fineractmysql:3306/fineract_tenants
+ - fineract_tenants_uid=root
+ - fineract_tenants_pwd=skdcnwauicn2ucnaecasdsajdnizucawencascdca
+ - FINERACT_DEFAULT_TENANTDB_HOSTNAME=fineractmysql
+ - FINERACT_DEFAULT_TENANTDB_PORT=3306
+ - FINERACT_DEFAULT_TENANTDB_UID=root
+ - FINERACT_DEFAULT_TENANTDB_PWD=skdcnwauicn2ucnaecasdsajdnizucawencascdca
+ - FINERACT_DEFAULT_TENANTDB_CONN_PARAMS=
+
+ # Frontend service
+ community-app:
+ image: openmf/community-app:latest
+ container_name: mifos-ui
+ restart: always
+ ports:
+ - 9090:80
+ networks:
+ - app-tier
+
+# https://issues.apache.org/jira/browse/FINERACT-762
+# To use an altnerative JDBC driver (which is faster, but not allowed to be default in Apache distribution)
+# replace org.drizzle.jdbc.DrizzleDriver with com.mysql.jdbc.Driver in DRIVERCLASS_NAME and fineract_tenants_driver,
+# and remove ":thin:" from SUB_PROTOCOL and fineract_tenants_url. Note that the mysql-connector-java-*.jar is already
+# bundled in the container by the Dockerfile, but just not used by default.
diff --git a/fineract-provider/dependencies.gradle b/fineract-provider/dependencies.gradle
index 2ab2467..019fe8c 100644
--- a/fineract-provider/dependencies.gradle
+++ b/fineract-provider/dependencies.gradle
@@ -69,6 +69,8 @@ dependencies {
'com.google.cloud.sql:mysql-socket-factory-connector-j-8:1.4.0',
'com.squareup.retrofit2:converter-gson',
+ 'com.sun.activation:jakarta.activation:1.2.2',
+ 'com.trendyol:Jdempotent-spring-boot-redis-starter:1.0.10'
)
implementation('org.springframework.boot:spring-boot-starter-jersey') {
diff --git a/fineract-provider/properties/basicauth/application.properties b/fineract-provider/properties/basicauth/application.properties
index 4a0e1dd..c9de2f2 100644
--- a/fineract-provider/properties/basicauth/application.properties
+++ b/fineract-provider/properties/basicauth/application.properties
@@ -30,3 +30,18 @@ management.info.git.mode=FULL
# FINERACT-914
server.forward-headers-strategy=framework
+
+# FINERACT-1420
+jdempotent.enable=false
+jdempotent.cryptography.algorithm=MD5
+jdempotent.cache.redis.database=9
+jdempotent.cache.redis.password=str0ng_passw0rd
+jdempotent.cache.redis.sentinelHostList=redis-sentinel
+jdempotent.cache.redis.sentinelPort=26379
+jdempotent.cache.redis.sentinelMasterName=mymaster
+jdempotent.cache.redis.expirationTimeHour=2
+jdempotent.cache.redis.dialTimeoutSecond=3
+jdempotent.cache.redis.readTimeoutSecond=3
+jdempotent.cache.redis.writeTimeoutSecond=3
+jdempotent.cache.redis.maxRetryCount=3
+jdempotent.cache.redis.expireTimeoutHour=84
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResource.java
index d01f4dc..485edaa 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResource.java
@@ -18,6 +18,8 @@
*/
package org.apache.fineract.portfolio.savings.api;
+import com.trendyol.jdempotent.core.annotation.JdempotentRequestPayload;
+import com.trendyol.jdempotent.core.annotation.JdempotentResource;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
@@ -31,9 +33,11 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
@@ -139,7 +143,9 @@ public class SavingsProductsApiResource {
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = SavingsProductsApiResourceSwagger.PostSavingsProductsRequest.class)))
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = SavingsProductsApiResourceSwagger.PostSavingsProductsResponse.class))) })
- public String create(@Parameter(hidden = true) final String apiRequestBodyAsJson) {
+ @JdempotentResource(ttl = 30, ttlTimeUnit = TimeUnit.SECONDS)
+ public String create(@JdempotentRequestPayload @HeaderParam("x-idempotency-key") String xIdempotencyKeyHeader,
+ @Parameter(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createSavingProduct().withJson(apiRequestBodyAsJson).build();
diff --git a/fineract-provider/src/main/resources/logback-spring.xml b/fineract-provider/src/main/resources/logback-spring.xml
index 99e6e8c..b8d2043 100644
--- a/fineract-provider/src/main/resources/logback-spring.xml
+++ b/fineract-provider/src/main/resources/logback-spring.xml
@@ -39,4 +39,5 @@
<!-- But these two INFO are still handy ;-) just to see when it's up and running -->
<logger name="org.springframework.boot.web.embedded.tomcat.TomcatWebServer" level="info" />
<logger name="org.apache.fineract.ServerApplication" level="info" />
+ <logger name="com.trendyol.jdempotent.core" level="DEBUG"/>
</configuration>