From 1d2bf3a668583728ef9cabb9167837f8addb12aa Mon Sep 17 00:00:00 2001 From: Rodrigo Maciel de Almeida Date: Sun, 14 Sep 2025 20:17:56 -0300 Subject: [PATCH] issue 21965 - [REQ] MergedSpecBuilder load servers urls from input specs --- .../codegen/config/MergedSpecBuilder.java | 27 ++++++++++++++----- .../codegen/config/MergedSpecBuilderTest.java | 15 +++++++++-- .../test/resources/bugs/mergerTest/spec1.json | 10 ++++++- .../test/resources/bugs/mergerTest/spec1.yaml | 5 +++- .../test/resources/bugs/mergerTest/spec2.json | 10 ++++++- .../test/resources/bugs/mergerTest/spec2.yaml | 5 +++- 6 files changed, 59 insertions(+), 13 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/MergedSpecBuilder.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/MergedSpecBuilder.java index 9a03113ec698..f56dc392e882 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/MergedSpecBuilder.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/config/MergedSpecBuilder.java @@ -5,7 +5,9 @@ import com.google.common.collect.ImmutableMap; import io.swagger.parser.OpenAPIParser; import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.servers.Server; import io.swagger.v3.parser.core.models.ParseOptions; +import org.apache.commons.lang3.ObjectUtils; import org.openapitools.codegen.auth.AuthParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,6 +19,7 @@ import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.*; +import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -58,6 +61,7 @@ public String buildMergedSpec() { ParseOptions options = new ParseOptions(); options.setResolve(true); List allPaths = new ArrayList<>(); + List allServers = new ArrayList<>(); for (String specRelatedPath : specRelatedPaths) { String specPath = inputSpecRootDirectory + File.separator + specRelatedPath; @@ -74,13 +78,14 @@ public String buildMergedSpec() { isJson = true; } } + allServers.addAll(ObjectUtils.defaultIfNull(result.getServers(), Collections.emptyList())); allPaths.add(new SpecWithPaths(specRelatedPath, result.getPaths().keySet())); } catch (Exception e) { LOGGER.error("Failed to read file: {}. It would be ignored", specPath); } } - Map mergedSpec = generatedMergedSpec(openapiVersion, allPaths); + Map mergedSpec = generatedMergedSpec(openapiVersion, allPaths, allServers); String mergedFilename = this.mergeFileName + (isJson ? ".json" : ".yaml"); Path mergedFilePath = Paths.get(inputSpecRootDirectory, mergedFilename); @@ -94,8 +99,8 @@ public String buildMergedSpec() { return mergedFilePath.toString(); } - private Map generatedMergedSpec(String openapiVersion, List allPaths) { - Map spec = generateHeader(openapiVersion, mergedFileInfoName, mergedFileInfoDescription, mergedFileInfoVersion); + private Map generatedMergedSpec(String openapiVersion, List allPaths, List allServers) { + Map spec = generateHeader(openapiVersion, mergedFileInfoName, mergedFileInfoDescription, mergedFileInfoVersion, allServers); Map paths = new HashMap<>(); spec.put("paths", paths); @@ -111,7 +116,7 @@ private Map generatedMergedSpec(String openapiVersion, List generateHeader(String openapiVersion, String title, String description, String version) { + private static Map generateHeader(String openapiVersion, String title, String description, String version, List allServers) { Map map = new HashMap<>(); map.put("openapi", openapiVersion); map.put("info", ImmutableMap.of( @@ -119,9 +124,17 @@ private static Map generateHeader(String openapiVersion, String "description", description, "version", version )); - map.put("servers", Collections.singleton( - ImmutableMap.of("url", "http://localhost:8080") - )); + + Set> servers = allServers.stream() + .map(Server::getUrl) + .distinct() + .map(url -> ImmutableMap.of("url", url)) + .collect(Collectors.collectingAndThen(Collectors.toSet(), Optional::of)) + .filter(Predicate.not(Set::isEmpty)) + .orElseGet(() -> Collections.singleton(ImmutableMap.of("url", "http://localhost:8080"))); + + map.put("servers", servers); + return map; } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/config/MergedSpecBuilderTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/config/MergedSpecBuilderTest.java index db4a33a2d4bb..42f9e0a547d1 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/config/MergedSpecBuilderTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/config/MergedSpecBuilderTest.java @@ -18,6 +18,8 @@ import java.util.function.Function; import java.util.stream.Collectors; +import static org.openapitools.codegen.languages.SpringCodegen.*; + public class MergedSpecBuilderTest { @Test @@ -55,6 +57,7 @@ private void assertFilesFromMergedSpec(String mergedSpec) throws IOException { .readLocation(mergedSpec, null, parseOptions).getOpenAPI(); SpringCodegen codegen = new SpringCodegen(); + codegen.additionalProperties().put(REQUEST_MAPPING_OPTION, "api_interface"); codegen.setOutputDir(output.getAbsolutePath()); ClientOptInput input = new ClientOptInput(); @@ -78,10 +81,18 @@ private void assertFilesFromMergedSpec(String mergedSpec) throws IOException { .assertParameter("param1") .hasType("String") .assertParameterAnnotations() - .containsWithNameAndAttributes("PathVariable", ImmutableMap.of("value", "\"param1\"")); + .containsWithNameAndAttributes("PathVariable", ImmutableMap.of("value", "\"param1\"")) + .toParameter() + .toMethod() + .toFileAssert() + .fileContains("@RequestMapping(\"${openapi.mergedSpec.base-path:/my-context-root/v1}\")") + ; JavaFileAssert.assertThat(files.get("Spec2Api.java")) - .assertMethod("spec2Operation").hasReturnType("ResponseEntity"); + .assertMethod("spec2Operation").hasReturnType("ResponseEntity") + .toFileAssert() + .fileContains("@RequestMapping(\"${openapi.mergedSpec.base-path:/my-context-root/v1}\")") + ; JavaFileAssert.assertThat(files.get("Spec1Model.java")) .assertMethod("getSpec1Field").hasReturnType("String"); diff --git a/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec1.json b/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec1.json index b29f7847b3fc..36c520ef2e95 100644 --- a/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec1.json +++ b/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec1.json @@ -5,6 +5,14 @@ "description": "Specification to reproduce nullable issue with Array", "title": "ArrayNullableTest Api" }, + "servers": [ + { + "url": "api.my-domain.com/my-context-root/v1" + }, + { + "url": "hom-api.my-domain.com/my-context-root/v1" + } + ], "paths": { "/spec1": { "get": { @@ -71,4 +79,4 @@ } } } -} \ No newline at end of file +} diff --git a/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec1.yaml b/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec1.yaml index d177198cedd2..f4fa54df63c6 100644 --- a/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec1.yaml +++ b/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec1.yaml @@ -3,6 +3,9 @@ info: version: 1.0.0 description: Specification to reproduce nullable issue with Array title: ArrayNullableTest Api +servers: + - url: api.my-domain.com/my-context-root/v1 + - url: hom-api.my-domain.com/my-context-root/v1 paths: /spec1: get: @@ -43,4 +46,4 @@ components: type: object properties: spec1Field: - type: string \ No newline at end of file + type: string diff --git a/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec2.json b/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec2.json index b7d83e5707b3..f06b20c172c2 100644 --- a/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec2.json +++ b/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec2.json @@ -5,6 +5,14 @@ "description": "Specification to reproduce nullable issue with Array", "title": "ArrayNullableTest Api" }, + "servers": [ + { + "url": "api.my-domain.com/my-context-root/v1" + }, + { + "url": "hom-api.my-domain.com/my-context-root/v1" + } + ], "paths": { "/spec2": { "get": { @@ -40,4 +48,4 @@ } } } -} \ No newline at end of file +} diff --git a/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec2.yaml b/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec2.yaml index bcd5f9a66b9a..183c0180d06d 100644 --- a/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec2.yaml +++ b/modules/openapi-generator/src/test/resources/bugs/mergerTest/spec2.yaml @@ -3,6 +3,9 @@ info: version: 1.0.0 description: Specification to reproduce nullable issue with Array title: ArrayNullableTest Api +servers: + - url: api.my-domain.com/my-context-root/v1 + - url: hom-api.my-domain.com/my-context-root/v1 paths: /spec2: get: @@ -24,4 +27,4 @@ components: type: object properties: spec2Field: - type: number \ No newline at end of file + type: number