Skip to content

Commit ed0e031

Browse files
spring-http-interface: introduce springHttpClientAdapter, fix paramDoc.mustache (#19710)
* spring-http-interface: introduce `springHttpClientAdapter`, fix `paramDoc.mustache` --- ### What - Introduce `springHttpClientAdapter` for `spring-http-interface` - This property is used for selecting HTTP client implementation in Spring HTTP interfaces, with separate templates for each client configuration - Added an `spring-http-interface`-specific **empty** `paramDoc.mustache` --- ### Why - Enable selecting different HTTP client implementations when generating Spring HTTP client interfaces - Provides additional flexibility for users who want to generate non-reactive Spring Boot applications. --- ### How - `springHttpClientAdapter`: Allows users to choose between different HTTP client implementations used in `HttpInterfacesAbstractConfigurator`: - `web-client` (set by default, to ensure **backward compatibility**) - `rest-client` - `rest-template` - Separate templates for each `HttpInterfacesAbstractConfigurator` implementation: - `httpInterfacesRestClientConfiguration.mustache` - `httpInterfacesRestTemplateConfiguration.mustache` - `httpInterfacesWebClientConfiguration.mustache` - Log warning for configuration mismatch - When `reactive: false` is used in combination with the reactive `web-client`, it warns users of potential configuration mismatches, and suggests switching to `rest-template` or `rest-client` for non-reactive configurations. - Remove unnecessary paramDoc - Added an `spring-http-interface`-specific **empty** `paramDoc.mustache` in `JavaSpring/libraries/spring-http-interface/paramDoc.mustache` - This prevents inheriting the `@Parameter` annotations from the default Spring template located at `JavaSpring/paramDoc.mustache`. - Otherwise, the generated code includes `@Parameter` annotations on request body parameters, which were causing compile errors due to missing imports --- ### Testing Done - **Manual testing**: Verified that the generated code uses `WebClient`, `RestTemplate`, or `RestClient` based on the value of the `springHttpClientAdapter` property. - **Tested different configurations**: - **`reactive: false` & `web-client`**: Logs a warning, suggesting the use of `rest-client` or `rest-template`. - **`springHttpClientAdapter: rest-template`**: Generates code with `RestTemplateAdapter` using the `httpInterfacesRestTemplateConfiguration.mustache`. - **`springHttpClientAdapter: web-client` (default)**: Generates code using `WebClientAdapter` from `httpInterfacesWebClientConfiguration.mustache` and ensures backward compatibility. - **Tested `paramDoc.mustache` change**: Verified that the empty `paramDoc.mustache` prevents the generation of `@Parameter` annotations on request body parameters and resolves the compile errors caused by missing imports. --- ### PR checklist - [ ] Read the [contribution guidelines](https://github.com/openapitools/openapi-generator/blob/master/CONTRIBUTING.md). - [ ] Pull Request title clearly describes the work in the pull request and Pull Request description provides details about how to validate the work. Missing information here may result in delayed response from the community. - [ ] Run the following to [build the project](https://github.com/OpenAPITools/openapi-generator#14---build-projects) and update samples: ``` ./mvnw clean package ./bin/generate-samples.sh ./bin/configs/*.yaml ./bin/utils/export_docs_generators.sh ``` (For Windows users, please run the script in [Git BASH](https://gitforwindows.org/)) Commit all changed files. This is important, as CI jobs will verify _all_ generator outputs of your HEAD commit as it would merge with master. These must match the expectations made by your contribution. You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example `./bin/generate-samples.sh bin/configs/java*`. IMPORTANT: Do **NOT** purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed. - [ ] File the PR against the [correct branch](https://github.com/OpenAPITools/openapi-generator/wiki/Git-Branches): `master` (upcoming `7.x.0` minor release - breaking changes with fallbacks), `8.0.x` (breaking changes without fallbacks) - [ ] If your PR is targeting a particular programming language, @mention the [technical committee](https://github.com/openapitools/openapi-generator/#62---openapi-generator-technical-committee) members, so they are more likely to review the pull request. * fix imports * Update SpringCodegen.java * fix docs and default value * fix docs and default value * revert to HttpServiceProxyFactory.builder for backward compatibility * spring-http-interface: introduce `useHttpServiceProxyFactoryInterfacesConfiguration` config * spring-http-interface: introduce `useHttpServiceProxyFactoryInterfacesConfigurator` config * spring-http-interface: introduce `useHttpServiceProxyFactoryInterfacesConfigurator` config * spring-http-interface: fix generated files * remove unnecessary imports from httpServiceProxyFactoryInterfacesConfigurator.mustache and parentOverrides from spring-http-interface-useHttpServiceProxyFactoryInterfacesConfiguration.yaml * remove unnecessary paramDoc.mustache, update `useHttpServiceProxyFactoryInterfacesConfigurator` parameter docs of `spring-http-interface` library * [java][spring] Spring HTTP Interface library: Validate Spring Boot version (3 or 4) and fail early if unsupported * Set `useSpringBoot3: "true"` for all sample configs using `library: spring-http-interface` * Regenerate samples using `library: spring-http-interface` * Update "spring-http-interface" docs "Spring 6 HTTP interfaces (testing)" -> "Spring 6 HTTP interfaces (testing). Requires Spring Boot 3 or 4." in java-camel.md and spring.md --------- Co-authored-by: Bragolgirith <6455473+Bragolgirith@users.noreply.github.com>
1 parent da3e824 commit ed0e031

80 files changed

Lines changed: 9580 additions & 23 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/samples-jdk17.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010
- samples/client/petstore/spring-http-interface/**
1111
- samples/client/petstore/spring-http-interface-reactive-noResponseEntity/**
1212
- samples/client/petstore/spring-http-interface-noResponseEntity/**
13+
- samples/client/petstore/spring-http-interface-useHttpServiceProxyFactoryInterfacesConfigurator/**
1314
- samples/client/petstore/java/webclient-jakarta/**
1415
- samples/client/petstore/java/microprofile-rest-client-outer-enum/**
1516
# servers
@@ -29,6 +30,7 @@ on:
2930
- samples/client/petstore/spring-http-interface/**
3031
- samples/client/petstore/spring-http-interface-reactive-noResponseEntity/**
3132
- samples/client/petstore/spring-http-interface-noResponseEntity/**
33+
- samples/client/petstore/spring-http-interface-useHttpServiceProxyFactoryInterfacesConfigurator/**
3234
- samples/client/petstore/java/webclient-jakarta/**
3335
- samples/client/petstore/java/microprofile-rest-client-outer-enum/**
3436
# servers
@@ -54,6 +56,7 @@ jobs:
5456
- samples/client/petstore/spring-http-interface
5557
- samples/client/petstore/spring-http-interface-reactive-noResponseEntity
5658
- samples/client/petstore/spring-http-interface-noResponseEntity
59+
- samples/client/petstore/spring-http-interface-useHttpServiceProxyFactoryInterfacesConfigurator
5760
- samples/client/petstore/java/webclient-jakarta
5861
- samples/client/petstore/java/microprofile-rest-client-outer-enum
5962
# servers

bin/configs/spring-http-interface-noResponseEntity.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ additionalProperties:
1717
useBeanValidation: "true"
1818
performBeanValidation: "true"
1919
useResponseEntity: "false"
20+
useSpringBoot3: "true"

bin/configs/spring-http-interface-reactive-noResponseEntity.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ additionalProperties:
1616
useBeanValidation: "true"
1717
performBeanValidation: "true"
1818
useResponseEntity: "false"
19+
useSpringBoot3: "true"
1920

bin/configs/spring-http-interface-reactive.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ additionalProperties:
1515
# validation should be ignored
1616
useBeanValidation: "true"
1717
performBeanValidation: "true"
18+
useSpringBoot3: "true"
1819

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
generatorName: spring
2+
library: spring-http-interface
3+
outputDir: samples/client/petstore/spring-http-interface-useHttpServiceProxyFactoryInterfacesConfigurator
4+
inputSpec: modules/openapi-generator/src/test/resources/3_0/spring/petstore-with-fake-endpoints-models-for-testing.yaml
5+
templateDir: modules/openapi-generator/src/main/resources/JavaSpring
6+
additionalProperties:
7+
artifactId: spring-http-interface-useHttpServiceProxyFactoryInterfacesConfigurator
8+
snapshotVersion: "true"
9+
hideGenerationTimestamp: "true"
10+
# documentation provider should be ignored
11+
documentationProvider: "springdoc"
12+
# annotation provider should be ignored
13+
annotationLibrary: "swagger2"
14+
# validation should be ignored
15+
useBeanValidation: "true"
16+
performBeanValidation: "true"
17+
useHttpServiceProxyFactoryInterfacesConfigurator: "true"
18+
useSpringBoot3: "true"

bin/configs/spring-http-interface.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ additionalProperties:
1616
# validation should be ignored
1717
useBeanValidation: "true"
1818
performBeanValidation: "true"
19+
useSpringBoot3: "true"

docs/generators/java-camel.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
7373
|interfaceOnly|Whether to generate only API interface stubs without the server files.| |false|
7474
|invokerPackage|root package for generated code| |org.openapitools.api|
7575
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|false|
76-
|library|library template (sub-template)|<dl><dt>**spring-boot**</dt><dd>Spring-boot Server application.</dd><dt>**spring-cloud**</dt><dd>Spring-Cloud-Feign client with Spring-Boot auto-configured settings.</dd><dt>**spring-http-interface**</dt><dd>Spring 6 HTTP interfaces (testing)</dd></dl>|spring-boot|
76+
|library|library template (sub-template)|<dl><dt>**spring-boot**</dt><dd>Spring-boot Server application.</dd><dt>**spring-cloud**</dt><dd>Spring-Cloud-Feign client with Spring-Boot auto-configured settings.</dd><dt>**spring-http-interface**</dt><dd>Spring 6 HTTP interfaces (testing). Requires Spring Boot 3 or 4.</dd></dl>|spring-boot|
7777
|licenseName|The name of the license| |Unlicense|
7878
|licenseUrl|The URL of the license| |http://unlicense.org|
7979
|modelPackage|package for generated models| |org.openapitools.model|
@@ -109,6 +109,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
109109
|useEnumCaseInsensitive|Use `equalsIgnoreCase` when String for enum comparison| |false|
110110
|useFeignClientContextId|Whether to generate Feign client with contextId parameter.| |true|
111111
|useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
112+
|useHttpServiceProxyFactoryInterfacesConfigurator|Generate HttpInterfacesAbstractConfigurator based on an HttpServiceProxyFactory instance (as opposed to a WebClient instance, when disabled) for generating Spring HTTP interfaces.| |false|
112113
|useJackson3|Set it in order to use jackson 3 dependencies (only allowed when `useSpringBoot4` is set and incompatible with `openApiNullable`).| |false|
113114
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
114115
|useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |true|

docs/generators/spring.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
6666
|interfaceOnly|Whether to generate only API interface stubs without the server files.| |false|
6767
|invokerPackage|root package for generated code| |org.openapitools.api|
6868
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|false|
69-
|library|library template (sub-template)|<dl><dt>**spring-boot**</dt><dd>Spring-boot Server application.</dd><dt>**spring-cloud**</dt><dd>Spring-Cloud-Feign client with Spring-Boot auto-configured settings.</dd><dt>**spring-http-interface**</dt><dd>Spring 6 HTTP interfaces (testing)</dd></dl>|spring-boot|
69+
|library|library template (sub-template)|<dl><dt>**spring-boot**</dt><dd>Spring-boot Server application.</dd><dt>**spring-cloud**</dt><dd>Spring-Cloud-Feign client with Spring-Boot auto-configured settings.</dd><dt>**spring-http-interface**</dt><dd>Spring 6 HTTP interfaces (testing). Requires Spring Boot 3 or 4.</dd></dl>|spring-boot|
7070
|licenseName|The name of the license| |Unlicense|
7171
|licenseUrl|The URL of the license| |http://unlicense.org|
7272
|modelPackage|package for generated models| |org.openapitools.model|
@@ -102,6 +102,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
102102
|useEnumCaseInsensitive|Use `equalsIgnoreCase` when String for enum comparison| |false|
103103
|useFeignClientContextId|Whether to generate Feign client with contextId parameter.| |true|
104104
|useFeignClientUrl|Whether to generate Feign client with url parameter.| |true|
105+
|useHttpServiceProxyFactoryInterfacesConfigurator|Generate HttpInterfacesAbstractConfigurator based on an HttpServiceProxyFactory instance (as opposed to a WebClient instance, when disabled) for generating Spring HTTP interfaces.| |false|
105106
|useJackson3|Set it in order to use jackson 3 dependencies (only allowed when `useSpringBoot4` is set and incompatible with `openApiNullable`).| |false|
106107
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
107108
|useOneOfInterfaces|whether to use a java interface to describe a set of oneOf options, where each option is a class that implements the interface| |true|

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ public class SpringCodegen extends AbstractJavaCodegen
8585
public static final String SPRING_BOOT = "spring-boot";
8686
public static final String SPRING_CLOUD_LIBRARY = "spring-cloud";
8787
public static final String SPRING_HTTP_INTERFACE = "spring-http-interface";
88+
public static final String USE_HTTP_SERVICE_PROXY_FACTORY_INTERFACES_CONFIGURATOR = "useHttpServiceProxyFactoryInterfacesConfigurator";
89+
public static final String HTTP_INTERFACES_CONFIGURATOR_DEPENDENCY = "httpInterfacesConfiguratorDependency";
8890
public static final String API_FIRST = "apiFirst";
8991
public static final String SPRING_CONTROLLER = "useSpringController";
9092
public static final String HATEOAS = "hateoas";
@@ -183,6 +185,7 @@ public enum RequestMappingMode {
183185
protected boolean useJackson3 = false;
184186
@Getter @Setter
185187
protected boolean additionalNotNullAnnotations = false;
188+
@Setter boolean useHttpServiceProxyFactoryInterfacesConfigurator = false;
186189

187190
public SpringCodegen() {
188191
super();
@@ -317,10 +320,14 @@ public SpringCodegen() {
317320

318321
cliOptions.add(CliOption.newBoolean(USE_DEDUCTION_FOR_ONE_OF_INTERFACES, "whether to use deduction for generated oneOf interfaces", useDeductionForOneOfInterfaces));
319322
cliOptions.add(CliOption.newString(SPRING_API_VERSION, "Value for 'version' attribute in @RequestMapping (for Spring 7 and above)."));
323+
cliOptions.add(CliOption.newString(USE_HTTP_SERVICE_PROXY_FACTORY_INTERFACES_CONFIGURATOR,
324+
"Generate HttpInterfacesAbstractConfigurator based on an HttpServiceProxyFactory instance (as opposed to a WebClient instance, when disabled) for generating Spring HTTP interfaces.")
325+
.defaultValue("false")
326+
);
320327
supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application.");
321328
supportedLibraries.put(SPRING_CLOUD_LIBRARY,
322329
"Spring-Cloud-Feign client with Spring-Boot auto-configured settings.");
323-
supportedLibraries.put(SPRING_HTTP_INTERFACE, "Spring 6 HTTP interfaces (testing)");
330+
supportedLibraries.put(SPRING_HTTP_INTERFACE, "Spring 6 HTTP interfaces (testing). Requires Spring Boot 3 or 4.");
324331
setLibrary(SPRING_BOOT);
325332
final CliOption library = new CliOption(CodegenConstants.LIBRARY, CodegenConstants.LIBRARY_DESC)
326333
.defaultValue(SPRING_BOOT);
@@ -542,7 +549,9 @@ public void processOpts() {
542549
} else {
543550
this.applyJackson2Package();
544551
}
552+
545553
convertPropertyToStringAndWriteBack(RESOURCE_FOLDER, this::setResourceFolder);
554+
convertPropertyToBooleanAndWriteBack(USE_HTTP_SERVICE_PROXY_FACTORY_INTERFACES_CONFIGURATOR, this::setUseHttpServiceProxyFactoryInterfacesConfigurator);
546555

547556
convertPropertyToBooleanAndWriteBack(ADDITIONAL_NOT_NULL_ANNOTATIONS, this::setAdditionalNotNullAnnotations);
548557

@@ -635,9 +644,23 @@ public void processOpts() {
635644
}
636645
}
637646
} else if (SPRING_HTTP_INTERFACE.equals(library)) {
638-
supportingFiles.add(new SupportingFile("httpInterfacesConfiguration.mustache",
647+
if (!(isUseSpringBoot3() || isUseSpringBoot4())) {
648+
throw new IllegalArgumentException("Library '" + SPRING_HTTP_INTERFACE + "' is only supported with Spring Boot 3 or 4");
649+
}
650+
651+
String httpInterfacesAbstractConfiguratorFile = useHttpServiceProxyFactoryInterfacesConfigurator ?
652+
"httpServiceProxyFactoryInterfacesConfigurator.mustache" :
653+
"httpInterfacesConfiguration.mustache";
654+
655+
supportingFiles.add(new SupportingFile(httpInterfacesAbstractConfiguratorFile,
639656
(sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "HttpInterfacesAbstractConfigurator.java"));
640657
writePropertyBack(USE_BEANVALIDATION, false);
658+
659+
writePropertyBack(HTTP_INTERFACES_CONFIGURATOR_DEPENDENCY,
660+
useHttpServiceProxyFactoryInterfacesConfigurator ?
661+
"HttpServiceProxyFactory" :
662+
reactive ? "WebClient" : "RestClient"
663+
);
641664
}
642665
}
643666

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# OpenAPI generated API stub
22

3-
[Spring Framework 6.1 HTTP Interface](https://docs.spring.io/spring-framework/docs/6.1.0/reference/html/integration.html#rest-http-interface)
3+
[Spring Framework 6.1 HTTP Interface](https://docs.spring.io/spring-framework/reference/integration/rest-clients.html#rest-http-interface)
44

55

66
## Overview
@@ -9,13 +9,13 @@ By using the [OpenAPI-Spec](https://openapis.org), you can easily generate an AP
99
This is an example of building API stub interfaces in Java using the Spring framework.
1010

1111
The stubs generated can be used in your existing Spring application for HTTP integration with other REST services
12-
To use auto-generated interfaces you have to create your own configuration which extends default abstract configurator & provide `{{#reactive}}WebClient{{/reactive}}{{^reactive}}RestClient{{/reactive}}` instance via constructor
12+
To use auto-generated interfaces you have to create your own configuration which extends default abstract configurator & provide `{{httpInterfacesConfiguratorDependency}}` instance via constructor
1313
```java
1414
@Configuration
1515
public class MyConfiguration extends {{configPackage}}.HttpInterfacesAbstractConfigurator {
1616
17-
public MyConfiguration({{#reactive}}WebClient{{/reactive}}{{^reactive}}RestClient{{/reactive}} client) {
18-
super(client);
17+
public MyConfiguration({{httpInterfacesConfiguratorDependency}} my{{httpInterfacesConfiguratorDependency}}) { // separately created {{httpInterfacesConfiguratorDependency}} instance
18+
super(my{{httpInterfacesConfiguratorDependency}});
1919
}
2020
}
2121
```

0 commit comments

Comments
 (0)