You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ar...@apache.org on 2022/11/30 07:58:48 UTC

[fineract] branch develop updated: FINERACT-1724: Fixed fineract-client generation to handle non-required request bodies in APIs

This is an automated email from the ASF dual-hosted git repository.

arnold 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 0c63bf2f2 FINERACT-1724: Fixed fineract-client generation to handle non-required request bodies in APIs
0c63bf2f2 is described below

commit 0c63bf2f27dc95ca4a066881ae2fc94427bbc9a7
Author: Arnold Galovics <ga...@gmail.com>
AuthorDate: Tue Nov 29 22:00:41 2022 +0100

    FINERACT-1724: Fixed fineract-client generation to handle non-required request bodies in APIs
---
 fineract-client/build.gradle                       |  15 +-
 .../src/main/resources/templates/java/api.mustache | 222 ++++++++++++++-------
 .../api/CreditBureauIntegrationAPI.java            |  25 +--
 3 files changed, 166 insertions(+), 96 deletions(-)

diff --git a/fineract-client/build.gradle b/fineract-client/build.gradle
index c95507a4d..ff891500d 100644
--- a/fineract-client/build.gradle
+++ b/fineract-client/build.gradle
@@ -110,15 +110,20 @@ task buildAsciidoc(type: org.openapitools.generator.gradle.plugin.tasks.Generate
     dependsOn(':fineract-provider:resolve')
 }
 
-task cleanupJodaImports() {
-    // This is a temporary step to get rid of joda imports in the generated code
-    // At this point it's unknown why it's even generated, probably it's a bug in the generator
+task cleanupGeneratedJavaFiles() {
     doLast {
         copy {
             from "$buildDir/generated/temp-java".toString()
             into "$buildDir/generated/java".toString()
             filter { line ->
-                line.replaceAll("import org\\.joda\\.time\\.\\*;", "")
+                line
+                        // This is a temporary step to get rid of joda imports in the generated code
+                        // At this point it's unknown why it's even generated, probably it's a bug in the generator
+                        .replaceAll("import org\\.joda\\.time\\.\\*;", "")
+                        // The 3 lines below handles the cases when a request body is not required
+                        .replaceAll(", \\)", ")")
+                        .replaceAll(", , @HeaderMap", ", @HeaderMap")
+                        .replaceAll("\\(, ", "(")
             }
         }
     }
@@ -127,7 +132,7 @@ task cleanupJodaImports() {
 }
 
 // TODO: @vidakovic we could provide even more client libs in different languages (Go, Ruby, Swift etc.)
-compileJava.dependsOn(buildJavaSdk, buildTypescriptAngularSdk, buildAsciidoc, cleanupJodaImports, licenseFormatMain, spotlessMiscApply)
+compileJava.dependsOn(buildJavaSdk, buildTypescriptAngularSdk, buildAsciidoc, cleanupGeneratedJavaFiles, licenseFormatMain, spotlessMiscApply)
 
 java {
     // keep this at Java 8, not 17; see https://issues.apache.org/jira/browse/FINERACT-1214
diff --git a/fineract-client/src/main/resources/templates/java/api.mustache b/fineract-client/src/main/resources/templates/java/api.mustache
index 65915d89f..e16793e38 100644
--- a/fineract-client/src/main/resources/templates/java/api.mustache
+++ b/fineract-client/src/main/resources/templates/java/api.mustache
@@ -3,17 +3,17 @@ package {{package}};
 import {{invokerPackage}}.CollectionFormats.*;
 
 {{#useRxJava2}}
-    import io.reactivex.Observable;
+import io.reactivex.Observable;
 {{/useRxJava2}}
 {{#useRxJava3}}
-    import io.reactivex.rxjava3.core.Observable;
+import io.reactivex.rxjava3.core.Observable;
 {{/useRxJava3}}
 {{^returnType}}
     {{#useRxJava2}}
-        import io.reactivex.Completable;
+import io.reactivex.Completable;
     {{/useRxJava2}}
     {{#useRxJava3}}
-        import io.reactivex.rxjava3.core.Completable;
+import io.reactivex.rxjava3.core.Completable;
     {{/useRxJava3}}
 {{/returnType}}
 {{#doNotUseRx}}
@@ -29,92 +29,174 @@ import okhttp3.MultipartBody;
 {{/imports}}
 
 {{^fullJavaUtil}}
-    import java.util.ArrayList;
-    import java.util.HashMap;
-    import java.util.List;
-    import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 {{/fullJavaUtil}}
 
 {{#operations}}
-    public interface {{classname}} {
-    {{#operation}}
+public interface {{classname}} {
+{{#operation}}
+    /**
+    * {{summary}}
+    * {{notes}}
+    {{#allParams}}
+        * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}
+    {{/allParams}}
+    * @return {{^doNotUseRx}}{{#useRxJava2}}{{#returnType}}Observable&lt;{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}&gt;{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable&lt;{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}&gt;{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{#doN [...]
+    {{#isDeprecated}}
+        * @deprecated
+    {{/isDeprecated}}
+    {{#externalDocs}}
+        * {{description}}
+        * @see <a href="{{url}}">{{summary}} Documentation</a>
+    {{/externalDocs}}
+    */
+    {{#isDeprecated}}
+        @Deprecated
+    {{/isDeprecated}}
+    {{#formParams}}
+        {{#-first}}
+            {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}}
+        {{/-first}}
+    {{/formParams}}
+    {{^formParams}}
+        {{#prioritizedContentTypes}}
+            {{#-first}}
+                @Headers({
+                "Content-Type:{{{mediaType}}}"
+                })
+            {{/-first}}
+        {{/prioritizedContentTypes}}
+    {{/formParams}}
+    @{{httpMethod}}("{{{path}}}")
+    {{^doNotUseRx}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#i [...]
+
+{{/operation}}
+
+{{#operation}}
+    {{#allParams}}
+        {{#isBodyParam}}
+            {{^required}}
         /**
         * {{summary}}
         * {{notes}}
-        {{#allParams}}
+    {{#allParams}}
             * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}
-        {{/allParams}}
+    {{/allParams}}
         * @return {{^doNotUseRx}}{{#useRxJava2}}{{#returnType}}Observable&lt;{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}&gt;{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable&lt;{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}&gt;{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{ [...]
-        {{#isDeprecated}}
+    {{#isDeprecated}}
             * @deprecated
-        {{/isDeprecated}}
-        {{#externalDocs}}
+    {{/isDeprecated}}
+    {{#externalDocs}}
             * {{description}}
             * @see <a href="{{url}}">{{summary}} Documentation</a>
-        {{/externalDocs}}
+    {{/externalDocs}}
         */
-        {{#isDeprecated}}
+    {{#isDeprecated}}
             @Deprecated
-        {{/isDeprecated}}
-        {{#formParams}}
+    {{/isDeprecated}}
+    {{#formParams}}
+        {{#-first}}
+            {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}}
+        {{/-first}}
+    {{/formParams}}
+    {{^formParams}}
+        {{#prioritizedContentTypes}}
             {{#-first}}
-                {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}}
+                    @Headers({
+                    "Content-Type:{{{mediaType}}}"
+                    })
             {{/-first}}
-        {{/formParams}}
-        {{^formParams}}
-            {{#prioritizedContentTypes}}
-                {{#-first}}
+        {{/prioritizedContentTypes}}
+    {{/formParams}}
+    @{{httpMethod}}("{{{path}}}")
+    {{^doNotUseRx}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#i [...]
+            {{/required}}
+        {{/isBodyParam}}
+    {{/allParams}}
+{{/operation}}
+
+{{#operation}}
+        /**
+        * {{summary}}
+        * {{notes}}
+    {{#allParams}}
+            * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}
+    {{/allParams}}
+        * @return {{^doNotUseRx}}{{#useRxJava2}}{{#returnType}}Observable&lt;{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}&gt;{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable&lt;{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}&gt;{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{ [...]
+    {{#isDeprecated}}
+            * @deprecated
+    {{/isDeprecated}}
+    {{#externalDocs}}
+            * {{description}}
+            * @see <a href="{{url}}">{{summary}} Documentation</a>
+    {{/externalDocs}}
+        */
+    {{#isDeprecated}}
+            @Deprecated
+    {{/isDeprecated}}
+    {{#formParams}}
+        {{#-first}}
+            {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}}
+        {{/-first}}
+    {{/formParams}}
+    {{^formParams}}
+        {{#prioritizedContentTypes}}
+            {{#-first}}
                     @Headers({
                     "Content-Type:{{{mediaType}}}"
                     })
-                {{/-first}}
-            {{/prioritizedContentTypes}}
-        {{/formParams}}
-        @{{httpMethod}}("{{{path}}}")
-        {{^doNotUseRx}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{#doNotUseRx}}Call< [...]
-        {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{^-last}}, {{/-last}}{{#-last}}
-                );{{/-last}}{{/allParams}}
+            {{/-first}}
+        {{/prioritizedContentTypes}}
+    {{/formParams}}
+    @{{httpMethod}}("{{{path}}}")
+    {{^doNotUseRx}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#i [...]
 
-    {{/operation}}
+{{/operation}}
 
-    {{#operation}}
-            /**
-            * {{summary}}
-            * {{notes}}
-        {{#allParams}}
-                * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}
-        {{/allParams}}
-            * @return {{^doNotUseRx}}{{#useRxJava2}}{{#returnType}}Observable&lt;{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}&gt;{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable&lt;{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}&gt;{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx [...]
-        {{#isDeprecated}}
-                * @deprecated
-        {{/isDeprecated}}
-        {{#externalDocs}}
-                * {{description}}
-                * @see <a href="{{url}}">{{summary}} Documentation</a>
-        {{/externalDocs}}
-            */
-        {{#isDeprecated}}
-                @Deprecated
-        {{/isDeprecated}}
-        {{#formParams}}
+{{#operation}}
+    {{#allParams}}
+        {{#isBodyParam}}
+            {{^required}}
+        /**
+        * {{summary}}
+        * {{notes}}
+    {{#allParams}}
+            * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}
+    {{/allParams}}
+        * @return {{^doNotUseRx}}{{#useRxJava2}}{{#returnType}}Observable&lt;{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}&gt;{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable&lt;{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{returnType}}{{/isResponseFile}}&gt;{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{ [...]
+    {{#isDeprecated}}
+            * @deprecated
+    {{/isDeprecated}}
+    {{#externalDocs}}
+            * {{description}}
+            * @see <a href="{{url}}">{{summary}} Documentation</a>
+    {{/externalDocs}}
+        */
+    {{#isDeprecated}}
+            @Deprecated
+    {{/isDeprecated}}
+    {{#formParams}}
+        {{#-first}}
+            {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}}
+        {{/-first}}
+    {{/formParams}}
+    {{^formParams}}
+        {{#prioritizedContentTypes}}
             {{#-first}}
-                {{#isMultipart}}@retrofit2.http.Multipart{{/isMultipart}}{{^isMultipart}}@retrofit2.http.FormUrlEncoded{{/isMultipart}}
+                    @Headers({
+                    "Content-Type:{{{mediaType}}}"
+                    })
             {{/-first}}
-        {{/formParams}}
-        {{^formParams}}
-            {{#prioritizedContentTypes}}
-                {{#-first}}
-                        @Headers({
-                        "Content-Type:{{{mediaType}}}"
-                        })
-                {{/-first}}
-            {{/prioritizedContentTypes}}
-        {{/formParams}}
-            @{{httpMethod}}("{{{path}}}")
-        {{^doNotUseRx}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{#doNotUseRx}}Call< [...]
-        {{#allParams}}{{>libraries/retrofit2/queryParams}}{{>libraries/retrofit2/pathParams}}{{>libraries/retrofit2/headerParams}}{{>libraries/retrofit2/bodyParams}}{{>libraries/retrofit2/formParams}}{{^-last}}, {{/-last}}{{#-last}}
-                , @HeaderMap Map<String, String> headers);{{/-last}}{{/allParams}}
-
-    {{/operation}}
-        }
+        {{/prioritizedContentTypes}}
+    {{/formParams}}
+    @{{httpMethod}}("{{{path}}}")
+    {{^doNotUseRx}}{{#useRxJava2}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava2}}{{#useRxJava3}}{{#returnType}}Observable<{{#isResponseFile}}ResponseBody{{/isResponseFile}}{{^isResponseFile}}{{{returnType}}}{{/isResponseFile}}>{{/returnType}}{{^returnType}}Completable{{/returnType}}{{/useRxJava3}}{{/doNotUseRx}}{{#doNotUseRx}}Call<{{#i [...]
+            {{/required}}
+        {{/isBodyParam}}
+    {{/allParams}}
+{{/operation}}
+}
 {{/operations}}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/api/CreditBureauIntegrationAPI.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/api/CreditBureauIntegrationAPI.java
index 2be61318e..d63401612 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/api/CreditBureauIntegrationAPI.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/creditbureau/api/CreditBureauIntegrationAPI.java
@@ -42,6 +42,7 @@ import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.UriInfo;
+import lombok.RequiredArgsConstructor;
 import org.apache.fineract.commands.domain.CommandWrapper;
 import org.apache.fineract.commands.service.CommandWrapperBuilder;
 import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -58,14 +59,12 @@ import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
 import org.glassfish.jersey.media.multipart.FormDataParam;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Scope;
 import org.springframework.stereotype.Component;
 import org.springframework.web.bind.annotation.RequestParam;
 
 @Path("/creditBureauIntegration")
 @Component
-@Scope("singleton")
+@RequiredArgsConstructor
 public class CreditBureauIntegrationAPI {
 
     private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "creditBureauId", "nrc", "creditReport"));
@@ -79,28 +78,12 @@ public class CreditBureauIntegrationAPI {
     private final DefaultToApiJsonSerializer<CreditReportData> toApiJsonSerializer;
     private static final Logger LOG = LoggerFactory.getLogger(CreditBureauIntegrationAPI.class);
 
-    @Autowired
-    public CreditBureauIntegrationAPI(final PlatformSecurityContext context,
-            final DefaultToApiJsonSerializer<CreditReportData> toCreditReportApiJsonSerializer,
-            final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
-            final ApiRequestParameterHelper apiRequestParameterHelper,
-            final CreditReportWritePlatformService creditReportWritePlatformService,
-            final CreditReportReadPlatformService creditReportReadPlatformService,
-            final DefaultToApiJsonSerializer<CreditReportData> toApiJsonSerializer) {
-        this.context = context;
-        this.toCreditReportApiJsonSerializer = toCreditReportApiJsonSerializer;
-        this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
-        this.apiRequestParameterHelper = apiRequestParameterHelper;
-        this.creditReportWritePlatformService = creditReportWritePlatformService;
-        this.creditReportReadPlatformService = creditReportReadPlatformService;
-        this.toApiJsonSerializer = toApiJsonSerializer;
-
-    }
-
     @POST
     @Path("creditReport")
     @Consumes({ MediaType.APPLICATION_JSON })
     @Produces({ MediaType.APPLICATION_JSON })
+    @RequestBody(description = "Fetch credit report", content = {
+            @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = Object.class)) })
     public String fetchCreditReport(@Context final UriInfo uriInfo, @RequestParam("params") final Map<String, Object> params) {
 
         Gson gson = new Gson();