Skip to content

Commit ef2fa03

Browse files
authored
[Java][Client] Add support for the new Spring RestClient (#18522)
* feat (JAVA SPRING RESTTEMPLATE) 17571: initial commit for Spring RestClient * feat (JAVA SPRING RESTTEMPLATE) 17571: Copied and changed the webclient mustache files The RestClient API is oriented on the WebClient API so many parts of the templates can be the same * fix (JAVA SPRING RESTTEMPLATE) 17571: Renaming error & add README template The README must be changed because the minimal Java Version for this client is 17 * fix (JAVA SPRING RESTTEMPLATE) 17571: Imports, compile errors and cookie setting * feat (JAVA SPRING RESTTEMPLATE) 17571: Add generated samples * test (JAVA SPRING RESTTEMPLATE) 17571: Add tests * feat (JAVA SPRING RESTTEMPLATE) 17571: Update doc * Add the restcilent to samples-java-client-jdk17.yam The minimum Java version of the used Spring Version is 17 * fix (JAVA SPRING RESTTEMPLATE) 17571: Workflow paths to petstore samples * fix (JAVA SPRING RESTTEMPLATE) 17571: Regenerated samples * feat (JAVA SPRING RESTTEMPLATE) 17571: Generated echo-api sample for RestClient * fix (JAVA SPRING RESTTEMPLATE) 17571: Missing import * fix (JAVA SPRING RESTTEMPLATE) 17571: Missing body class exception when null body is set * test (JAVA SPRING RESTTEMPLATE) 17571: Add echo-api Auth test * fix (JAVA SPRING RESTTEMPLATE) 17571: Gradlew file permissions * feat (JAVA SPRING RESTTEMPLATE) 17571: Reggenerate samples after rebase * test (JAVA SPRING RESTTEMPLATE) 17571: Add echo-api Body gif test * test (JAVA SPRING RESTTEMPLATE) 17571: Add echo-api octet stream body test * test (JAVA SPRING RESTTEMPLATE) 17571: Add echo-api multipart form data test * fix (JAVA SPRING RESTTEMPLATE) 17571: Form as body when body is null Also regenerated the restclient samples
1 parent d573f00 commit ef2fa03

578 files changed

Lines changed: 70301 additions & 6 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.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Java Client (Echo API) JDK17
2+
3+
on:
4+
push:
5+
paths:
6+
- samples/client/echo_api/java/restclient
7+
pull_request:
8+
paths:
9+
- samples/client/echo_api/java/restclient
10+
jobs:
11+
build:
12+
name: Build Java Client JDK17
13+
runs-on: ubuntu-latest
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
sample:
18+
# clients
19+
- samples/client/echo_api/java/restclient
20+
steps:
21+
- uses: actions/checkout@v4
22+
- uses: actions/setup-java@v4
23+
with:
24+
distribution: 'temurin'
25+
java-version: 17
26+
- name: Cache maven dependencies
27+
uses: actions/cache@v4
28+
env:
29+
cache-name: maven-repository
30+
with:
31+
path: |
32+
~/.m2
33+
key: ${{ runner.os }}-${{ github.job }}-${{ env.cache-name }}-${{ hashFiles('**/pom.xml') }}
34+
- name: Setup node.js
35+
uses: actions/setup-node@v4
36+
- name: Run echo server
37+
run: |
38+
git clone https://github.com/wing328/http-echo-server -b openapi-generator-test-server
39+
(cd http-echo-server && npm install && npm start &)
40+
- name: Build
41+
working-directory: ${{ matrix.sample }}
42+
run: mvn clean package

.github/workflows/samples-java-client-jdk17.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ on:
55
paths:
66
- samples/client/petstore/java/resttemplate-jakarta/**
77
- samples/client/petstore/java/webclient-jakarta/**
8+
- samples/client/petstore/java/restclient-*/**
89
pull_request:
910
paths:
1011
- samples/client/petstore/java/resttemplate-jakarta/**
1112
- samples/client/petstore/java/webclient-jakarta/**
13+
- samples/client/petstore/java/restclient-*/**
1214
jobs:
1315
build:
1416
name: Build Java Client JDK17
@@ -20,6 +22,9 @@ jobs:
2022
# clients
2123
- samples/client/petstore/java/resttemplate-jakarta
2224
- samples/client/petstore/java/webclient-jakarta
25+
- samples/client/petstore/java/restclient
26+
- samples/client/petstore/java/restclient-nullable-arrays
27+
- samples/client/petstore/java/restclient-swagger2
2328
steps:
2429
- uses: actions/checkout@v4
2530
- uses: actions/setup-java@v4
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
generatorName: java
2+
outputDir: samples/client/echo_api/java/restclient
3+
library: restclient
4+
inputSpec: modules/openapi-generator/src/test/resources/3_0/echo_api.yaml
5+
templateDir: modules/openapi-generator/src/main/resources/Java
6+
additionalProperties:
7+
artifactId: echo-api-native
8+
hideGenerationTimestamp: "true"
9+
10+
typeMappings:
11+
OffsetDateTime: "Instant"
12+
importMappings:
13+
OffsetDateTime: "java.time.Instant"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
generatorName: java
2+
outputDir: samples/client/petstore/java/restclient-nullable-arrays
3+
library: restclient
4+
inputSpec: modules/openapi-generator/src/test/resources/3_0/schema-with-nullable-arrays.yaml
5+
templateDir: modules/openapi-generator/src/main/resources/Java
6+
additionalProperties:
7+
artifactId: petstore-restclient-nullable-arrays
8+
hideGenerationTimestamp: "true"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
generatorName: java
2+
outputDir: samples/client/petstore/java/restclient-swagger2
3+
library: restclient
4+
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
5+
templateDir: modules/openapi-generator/src/main/resources/Java
6+
additionalProperties:
7+
artifactId: petstore-restclient
8+
hideGenerationTimestamp: "true"
9+
containerDefaultToNull: "true"
10+
annotationLibrary: "swagger2"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
generatorName: java
2+
outputDir: samples/client/others/java/restclient-useAbstractionForFiles
3+
library: restclient
4+
inputSpec: modules/openapi-generator/src/test/resources/3_0/issue13146_file_abstraction_response.yaml
5+
templateDir: modules/openapi-generator/src/main/resources/Java
6+
additionalProperties:
7+
artifactId: file-restclient
8+
hideGenerationTimestamp: "true"
9+
useAbstractionForFiles: true

bin/configs/java-restclient.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
generatorName: java
2+
outputDir: samples/client/petstore/java/restclient
3+
library: restclient
4+
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
5+
templateDir: modules/openapi-generator/src/main/resources/Java
6+
additionalProperties:
7+
artifactId: petstore-restclient
8+
hideGenerationTimestamp: "true"
9+
containerDefaultToNull: "true"

docs/generators/java.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
5858
|implicitHeadersRegex|Skip header parameters that matches given regex in the generated API methods using @ApiImplicitParams annotation. Note: this parameter is ignored when implicitHeaders=true| |null|
5959
|invokerPackage|root package for generated code| |org.openapitools.client|
6060
|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>|true|
61-
|library|library template (sub-template) to use|<dl><dt>**jersey2**</dt><dd>HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.9.x</dd><dt>**jersey3**</dt><dd>HTTP client: Jersey client 3.x. JSON processing: Jackson 2.x</dd><dt>**feign**</dt><dd>HTTP client: OpenFeign 10.x. JSON processing: Jackson 2.9.x. or Gson 2.x</dd><dt>**okhttp-gson**</dt><dd>[DEFAULT] HTTP client: OkHttp 3.x. JSON processing: Gson 2.8.x. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'.</dd><dt>**retrofit2**</dt><dd>HTTP client: OkHttp 3.x. JSON processing: Gson 2.x (Retrofit 2.3.0). Enable the RxJava adapter using '-DuseRxJava[2/3]=true'. (RxJava 1.x or 2.x or 3.x)</dd><dt>**resttemplate**</dt><dd>HTTP client: Spring RestTemplate 4.x. JSON processing: Jackson 2.9.x</dd><dt>**webclient**</dt><dd>HTTP client: Spring WebClient 5.x. JSON processing: Jackson 2.9.x</dd><dt>**resteasy**</dt><dd>HTTP client: Resteasy client 3.x. JSON processing: Jackson 2.9.x</dd><dt>**vertx**</dt><dd>HTTP client: VertX client 3.x. JSON processing: Jackson 2.9.x</dd><dt>**google-api-client**</dt><dd>HTTP client: Google API client 1.x. JSON processing: Jackson 2.9.x</dd><dt>**rest-assured**</dt><dd>HTTP client: rest-assured : 4.x. JSON processing: Gson 2.x or Jackson 2.10.x. Only for Java 8</dd><dt>**native**</dt><dd>HTTP client: Java native HttpClient. JSON processing: Jackson 2.9.x. Only for Java11+</dd><dt>**microprofile**</dt><dd>HTTP client: Microprofile client 1.x. JSON processing: JSON-B or Jackson 2.9.x</dd><dt>**apache-httpclient**</dt><dd>HTTP client: Apache httpclient 5.x</dd></dl>|okhttp-gson|
61+
|library|library template (sub-template) to use|<dl><dt>**jersey2**</dt><dd>HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.9.x</dd><dt>**jersey3**</dt><dd>HTTP client: Jersey client 3.x. JSON processing: Jackson 2.x</dd><dt>**feign**</dt><dd>HTTP client: OpenFeign 10.x. JSON processing: Jackson 2.9.x. or Gson 2.x</dd><dt>**okhttp-gson**</dt><dd>[DEFAULT] HTTP client: OkHttp 3.x. JSON processing: Gson 2.8.x. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'.</dd><dt>**retrofit2**</dt><dd>HTTP client: OkHttp 3.x. JSON processing: Gson 2.x (Retrofit 2.3.0). Enable the RxJava adapter using '-DuseRxJava[2/3]=true'. (RxJava 1.x or 2.x or 3.x)</dd><dt>**resttemplate**</dt><dd>HTTP client: Spring RestTemplate 4.x. JSON processing: Jackson 2.9.x</dd><dt>**webclient**</dt><dd>HTTP client: Spring WebClient 5.x. JSON processing: Jackson 2.9.x</dd><dt>**restclient**</dt><dd>HTTP client: Spring RestClient 6.1. JSON processing: Jackson 2.9.x</dd><dt>**resteasy**</dt><dd>HTTP client: Resteasy client 3.x. JSON processing: Jackson 2.9.x</dd><dt>**vertx**</dt><dd>HTTP client: VertX client 3.x. JSON processing: Jackson 2.9.x</dd><dt>**google-api-client**</dt><dd>HTTP client: Google API client 1.x. JSON processing: Jackson 2.9.x</dd><dt>**rest-assured**</dt><dd>HTTP client: rest-assured : 4.x. JSON processing: Gson 2.x or Jackson 2.10.x. Only for Java 8</dd><dt>**native**</dt><dd>HTTP client: Java native HttpClient. JSON processing: Jackson 2.9.x. Only for Java11+</dd><dt>**microprofile**</dt><dd>HTTP client: Microprofile client 1.x. JSON processing: JSON-B or Jackson 2.9.x</dd><dt>**apache-httpclient**</dt><dd>HTTP client: Apache httpclient 5.x</dd></dl>|okhttp-gson|
6262
|licenseName|The name of the license| |Unlicense|
6363
|licenseUrl|The URL of the license| |http://unlicense.org|
6464
|microprofileFramework|Framework for microprofile. Possible values &quot;kumuluzee&quot;| |null|
@@ -84,7 +84,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
8484
|supportStreaming|Support streaming endpoint (beta)| |false|
8585
|supportUrlQuery|Generate toUrlQueryString in POJO (default to true). Available on `native`, `apache-httpclient` libraries.| |false|
8686
|testOutput|Set output folder for models and APIs tests| |${project.build.directory}/generated-test-sources/openapi|
87-
|useAbstractionForFiles|Use alternative types instead of java.io.File to allow passing bytes without a file on disk. Available on resttemplate, webclient, libraries| |false|
87+
|useAbstractionForFiles|Use alternative types instead of java.io.File to allow passing bytes without a file on disk. Available on resttemplate, webclient, restclient, libraries| |false|
8888
|useBeanValidation|Use BeanValidation API annotations| |false|
8989
|useEnumCaseInsensitive|Use `equalsIgnoreCase` when String for enum comparison| |false|
9090
|useGzipFeature|Send gzip-encoded requests| |false|

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
8383
public static final String RESTEASY = "resteasy";
8484
public static final String RESTTEMPLATE = "resttemplate";
8585
public static final String WEBCLIENT = "webclient";
86+
public static final String RESTCLIENT = "restclient";
8687
public static final String REST_ASSURED = "rest-assured";
8788
public static final String RETROFIT_2 = "retrofit2";
8889
public static final String VERTX = "vertx";
@@ -216,7 +217,7 @@ public JavaClientCodegen() {
216217
cliOptions.add(CliOption.newBoolean(CASE_INSENSITIVE_RESPONSE_HEADERS, "Make API response's headers case-insensitive. Available on " + OKHTTP_GSON + ", " + JERSEY2 + " libraries"));
217218
cliOptions.add(CliOption.newString(MICROPROFILE_FRAMEWORK, "Framework for microprofile. Possible values \"kumuluzee\""));
218219
cliOptions.add(CliOption.newString(MICROPROFILE_MUTINY, "Whether to use async types for microprofile (currently only Smallrye Mutiny is supported)."));
219-
cliOptions.add(CliOption.newBoolean(USE_ABSTRACTION_FOR_FILES, "Use alternative types instead of java.io.File to allow passing bytes without a file on disk. Available on resttemplate, webclient, libraries"));
220+
cliOptions.add(CliOption.newBoolean(USE_ABSTRACTION_FOR_FILES, "Use alternative types instead of java.io.File to allow passing bytes without a file on disk. Available on resttemplate, webclient, restclient, libraries"));
220221
cliOptions.add(CliOption.newBoolean(DYNAMIC_OPERATIONS, "Generate operations dynamically at runtime from an OAS", this.dynamicOperations));
221222
cliOptions.add(CliOption.newBoolean(SUPPORT_STREAMING, "Support streaming endpoint (beta)", this.supportStreaming));
222223
cliOptions.add(CliOption.newBoolean(CodegenConstants.WITH_AWSV4_SIGNATURE_COMMENT, CodegenConstants.WITH_AWSV4_SIGNATURE_COMMENT_DESC + " (only available for okhttp-gson library)", this.withAWSV4Signature));
@@ -238,6 +239,7 @@ public JavaClientCodegen() {
238239
supportedLibraries.put(RETROFIT_2, "HTTP client: OkHttp 3.x. JSON processing: Gson 2.x (Retrofit 2.3.0). Enable the RxJava adapter using '-DuseRxJava[2/3]=true'. (RxJava 1.x or 2.x or 3.x)");
239240
supportedLibraries.put(RESTTEMPLATE, "HTTP client: Spring RestTemplate 4.x. JSON processing: Jackson 2.9.x");
240241
supportedLibraries.put(WEBCLIENT, "HTTP client: Spring WebClient 5.x. JSON processing: Jackson 2.9.x");
242+
supportedLibraries.put(RESTCLIENT, "HTTP client: Spring RestClient 6.1. JSON processing: Jackson 2.9.x");
241243
supportedLibraries.put(RESTEASY, "HTTP client: Resteasy client 3.x. JSON processing: Jackson 2.9.x");
242244
supportedLibraries.put(VERTX, "HTTP client: VertX client 3.x. JSON processing: Jackson 2.9.x");
243245
supportedLibraries.put(GOOGLE_API_CLIENT, "HTTP client: Google API client 1.x. JSON processing: Jackson 2.9.x");
@@ -300,7 +302,7 @@ public void addOperationToGroup(String tag, String resourcePath, Operation opera
300302

301303
@Override
302304
public void processOpts() {
303-
if (WEBCLIENT.equals(getLibrary()) || NATIVE.equals(getLibrary())) {
305+
if (WEBCLIENT.equals(getLibrary()) || NATIVE.equals(getLibrary()) || RESTCLIENT.equals(getLibrary())) {
304306
dateLibrary = "java8";
305307
} else if (MICROPROFILE.equals(getLibrary())) {
306308
dateLibrary = "legacy";
@@ -508,7 +510,7 @@ public void processOpts() {
508510
}
509511

510512
// helper for client library that allow to parse/format java.time.OffsetDateTime or org.threeten.bp.OffsetDateTime
511-
if (additionalProperties.containsKey("jsr310") && (isLibrary(WEBCLIENT) || isLibrary(VERTX) || isLibrary(RESTTEMPLATE) || isLibrary(RESTEASY) || isLibrary(MICROPROFILE) || isLibrary(JERSEY2) || isLibrary(JERSEY3) || isLibrary(APACHE))) {
513+
if (additionalProperties.containsKey("jsr310") && (isLibrary(WEBCLIENT) || isLibrary(VERTX) || isLibrary(RESTTEMPLATE) || isLibrary(RESTEASY) || isLibrary(MICROPROFILE) || isLibrary(JERSEY2) || isLibrary(JERSEY3) || isLibrary(APACHE) || isLibrary(RESTCLIENT))) {
512514
supportingFiles.add(new SupportingFile("JavaTimeFormatter.mustache", invokerFolder, "JavaTimeFormatter.java"));
513515
}
514516

@@ -556,7 +558,7 @@ public void processOpts() {
556558
reservedWords.remove("file");
557559
}
558560

559-
if (!(FEIGN.equals(getLibrary()) || RESTTEMPLATE.equals(getLibrary()) || RETROFIT_2.equals(getLibrary()) || GOOGLE_API_CLIENT.equals(getLibrary()) || REST_ASSURED.equals(getLibrary()) || WEBCLIENT.equals(getLibrary()) || MICROPROFILE.equals(getLibrary()))) {
561+
if (!(FEIGN.equals(getLibrary()) || RESTTEMPLATE.equals(getLibrary()) || RETROFIT_2.equals(getLibrary()) || GOOGLE_API_CLIENT.equals(getLibrary()) || REST_ASSURED.equals(getLibrary()) || WEBCLIENT.equals(getLibrary()) || MICROPROFILE.equals(getLibrary()) || RESTCLIENT.equals(getLibrary()))) {
560562
supportingFiles.add(new SupportingFile("apiException.mustache", invokerFolder, "ApiException.java"));
561563
supportingFiles.add(new SupportingFile("Configuration.mustache", invokerFolder, "Configuration.java"));
562564
supportingFiles.add(new SupportingFile("Pair.mustache", invokerFolder, "Pair.java"));
@@ -659,6 +661,9 @@ public void processOpts() {
659661
supportingFiles.add(new SupportingFile("auth/Authentication.mustache", authFolder, "Authentication.java"));
660662
} else if (WEBCLIENT.equals(getLibrary())) {
661663
forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON);
664+
} else if (RESTCLIENT.equals(getLibrary())) {
665+
forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON);
666+
applyJakartaPackage();
662667
} else if (VERTX.equals(getLibrary())) {
663668
typeMapping.put("file", "AsyncFile");
664669
importMapping.put("AsyncFile", "io.vertx.core.file.AsyncFile");

0 commit comments

Comments
 (0)