OpenAPITools / OpenAPITools/openapi-generator

[BUG] [Spring] Wrong code generated using "x-spring-provide-args" and delegate.

Open
#17,040 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

After make use of latest implemented extension "x-spring-provide-args" in combination with delegate strategy, the output code is not correct as the extra arguments has not been created in the delegate method and call.

openapi-generator version

Latest from master git since the addition of the "x-spring-provide-args" extension. See PR #16663

OpenAPI declaration file content or url

Use the sample pet store petstore-with-spring-provide-args.yaml

Generation Details

Run generation of "spring" code with delegatePattern=true. The generated code will build correctly, but the generated delegate will ignore any of the extra arguments making this solution incompatible with the delegate pattern.

Steps to reproduce

Just generate the pet store sample with the delegatePattern=true, the generated server will compile correctly but new added arguments can not be used in the delegate.

Related issues/PRs

PR #16663

Suggest a fix
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java
index 92a8883d33f..65bc2bc154c 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java
@@ -1320,6 +1320,8 @@ public class SpringCodegen extends AbstractJavaCodegen
             List<String> provideArgs = (List<String>) argObj;
             if (!provideArgs.isEmpty()) {
                 List<String> formatedArgs = new ArrayList<>();
+                List<String> formatedDelegateArgs = new ArrayList<>();
+                List<String> formatedDlegateCallArgs = new ArrayList<>();
                 for (String oneArg : provideArgs) {
                     if (StringUtils.isNotEmpty(oneArg)) {
                         String regexp = "(?<AnnotationTag>@)?(?<ClassPath>(?<PackageName>(\\w+\\.)*)(?<ClassName>\\w+))(?<Params>\\(.*?\\))?\\s?";
@@ -1340,11 +1342,25 @@ public class SpringCodegen extends AbstractJavaCodegen
                             }
                         }
                         String newArg = String.join(" ", newArgs);
+                        if (newArgs.size() > 1) {
+                            formatedDelegateArgs.add(
+                                    String.join(" ", newArgs.subList(newArgs.size() - 2, newArgs.size())));
+                            formatedDlegateCallArgs.add(newArgs.get(newArgs.size() - 1));
+                        } else {
+                            formatedDelegateArgs.add(newArg);
+                            formatedDlegateCallArgs.add(newArg);
+                        }
                         LOGGER.trace("new arg {} {}", newArg);
+                        LOGGER.trace("new delegate arg {} {}",
+                                formatedDelegateArgs.get(formatedDelegateArgs.size() - 1));
+                        LOGGER.trace("new delegate call arg {} {}",
+                                formatedDelegateArgs.get(formatedDelegateArgs.size() - 1));
                         formatedArgs.add(newArg);
                     }
                 }
                 operation.getExtensions().put("x-spring-provide-args", formatedArgs);
+                operation.getExtensions().put("x-spring-provide-args-delegate", formatedDelegateArgs);
+                operation.getExtensions().put("x-spring-provide-args-delegate-call", formatedDlegateCallArgs);
             }
         }
         return provideArgsClassSet;
diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache
index 712b7b6ccc5..b9cace80d28 100644
--- a/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache
+++ b/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache
@@ -256,11 +256,11 @@ public interface {{classname}} {
         {{/-last}}{{/hasParams}}{{/vendorExtensions.x-spring-provide-args}}
     ){{#unhandledException}} throws Exception{{/unhandledException}}{{^jdk8-default-interface}};{{/jdk8-default-interface}}{{#jdk8-default-interface}} {
         {{#delegate-method}}
-        {{^isVoid}}return {{/isVoid}}{{#isVoid}}{{#useResponseEntity}}return {{/useResponseEntity}}{{^useResponseEntity}}{{#reactive}}return {{/reactive}}{{/useResponseEntity}}{{/isVoid}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}{{#hasParams}}, {{/hasParams}}{{^hasParams}}{{#reactive}}, {{/reactive}}{{/hasParams}}pageable{{/vendorExtensions.x-spring-paginated}});
+        {{^isVoid}}return {{/isVoid}}{{#isVoid}}{{#useResponseEntity}}return {{/useResponseEntity}}{{^useResponseEntity}}{{#reactive}}return {{/reactive}}{{/useResponseEntity}}{{/isVoid}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}{{#hasParams}}, {{/hasParams}}{{^hasParams}}{{#reactive}}, {{/reactive}}{{/hasParams}}pageable{{/vendorExtensions.x-spring-paginated}}{{#vendorExtensions.x-spring-provide-args-delegate-call}}{{#hasParams}},{{/hasParams}}{{^hasParams}}{{#reactive}},{{/reactive}}{{/hasParams}} {{{.}}}{{^hasParams}}{{^-last}}{{^reactive}},{{/reactive}}{{/-last}}{{/hasParams}}{{/vendorExtensions.x-spring-provide-args-delegate-call}});
     }
 
     // Override this method
-    {{#jdk8-default-interface}}default {{/jdk8-default-interface}} {{>responseType}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#reactive}}Flux<Part>{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}{{#springFoxDocumentationProvider}}@ApiIgnore{{/springFoxDocumentationProvider}} final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}{{#hasParams}}, {{/hasParams}}{{^hasParams}}{{#reactive}}, {{/reactive}}{{/hasParams}}{{#springFoxDocumentationProvider}}@ApiIgnore{{/springFoxDocumentationProvider}}final Pageable pageable{{/vendorExtensions.x-spring-paginated}}){{#unhandledException}} throws Exception{{/unhandledException}} {
+    {{#jdk8-default-interface}}default {{/jdk8-default-interface}} {{>responseType}} {{operationId}}({{#allParams}}{{^isFile}}{{^isBodyParam}}{{>optionalDataType}}{{/isBodyParam}}{{#isBodyParam}}{{^reactive}}{{{dataType}}}{{/reactive}}{{#reactive}}{{^isArray}}Mono<{{{dataType}}}>{{/isArray}}{{#isArray}}Flux<{{{baseType}}}>{{/isArray}}{{/reactive}}{{/isBodyParam}}{{/isFile}}{{#isFile}}{{#reactive}}Flux<Part>{{/reactive}}{{^reactive}}MultipartFile{{/reactive}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}{{#reactive}}{{#hasParams}}, {{/hasParams}}{{#springFoxDocumentationProvider}}@ApiIgnore{{/springFoxDocumentationProvider}} final ServerWebExchange exchange{{/reactive}}{{#vendorExtensions.x-spring-paginated}}{{#hasParams}}, {{/hasParams}}{{^hasParams}}{{#reactive}}, {{/reactive}}{{/hasParams}}{{#springFoxDocumentationProvider}}@ApiIgnore{{/springFoxDocumentationProvider}}final Pageable pageable{{/vendorExtensions.x-spring-paginated}}{{#vendorExtensions.x-spring-provide-args-delegate}}{{#hasParams}},{{/hasParams}}{{^hasParams}}{{#reactive}},{{/reactive}}{{/hasParams}} {{{.}}}{{^hasParams}}{{^-last}}{{^reactive}},{{/reactive}}{{/-last}}{{/hasParams}}{{/vendorExtensions.x-spring-provide-args-delegate}}){{#unhandledException}} throws Exception{{/unhandledException}} {
         {{/delegate-method}}
         {{^isDelegate}}
         {{>methodBody}}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java and modules/openapi-generator/src/main/resources/JavaSpring/api.mustache. Generate the petstore-with-spring-provide-args.yaml sample with delegatePattern=true and inspect the generated delegate method and call. Done means the extra x-spring-provide-args parameters are available in both the delegate signature and invocation, while the generated server still compiles.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.