Skip to content

Commit a62cdba

Browse files
committed
feat: add support for Jackson 3 and Spring Boot 4 in Java resttemplate client generation
1 parent 94fcce5 commit a62cdba

8 files changed

Lines changed: 168 additions & 66 deletions

File tree

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
push:
55
paths:
66
- samples/client/petstore/java/resttemplate-jakarta/**
7+
- samples/client/petstore/java/resttemplate-springBoot4-*/**
78
- samples/client/petstore/java/webclient-jakarta/**
89
- samples/client/petstore/java/restclient-*/**
910
- samples/client/others/java/webclient-sealedInterface/**
@@ -13,6 +14,7 @@ on:
1314
pull_request:
1415
paths:
1516
- samples/client/petstore/java/resttemplate-jakarta/**
17+
- samples/client/petstore/java/resttemplate-springBoot4-*/**
1618
- samples/client/petstore/java/webclient-jakarta/**
1719
- samples/client/petstore/java/restclient-*/**
1820
- samples/client/others/java/webclient-sealedInterface/**
@@ -29,6 +31,8 @@ jobs:
2931
sample:
3032
# clients
3133
- samples/client/petstore/java/resttemplate-jakarta
34+
- samples/client/petstore/java/resttemplate-springBoot4-jackson2
35+
- samples/client/petstore/java/resttemplate-springBoot4-jackson3
3236
- samples/client/petstore/java/webclient-jakarta
3337
- samples/client/petstore/java/restclient
3438
- samples/client/petstore/java/restclient-nullable-arrays
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
generatorName: java
2+
outputDir: samples/client/petstore/java/resttemplate-springBoot4-jackson2
3+
library: resttemplate
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-resttemplate
8+
hideGenerationTimestamp: "true"
9+
containerDefaultToNull: "true"
10+
useJakartaEe: true
11+
useSpringBoot4: true
12+
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/petstore/java/resttemplate-springBoot4-jackson3
3+
library: resttemplate
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-resttemplate
8+
hideGenerationTimestamp: "true"
9+
containerDefaultToNull: "true"
10+
useJakartaEe: true
11+
useSpringBoot4: true
12+
useJackson3: true
13+
openApiNullable: false

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

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
import static com.google.common.base.CaseFormat.LOWER_CAMEL;
4848
import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
4949
import static java.util.Collections.sort;
50-
import static org.openapitools.codegen.CodegenConstants.SERIALIZATION_LIBRARY;
5150
import static org.openapitools.codegen.CodegenConstants.X_IMPLEMENTS;
5251
import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER;
5352
import static org.openapitools.codegen.utils.StringUtils.camelize;
@@ -132,50 +131,87 @@ public class JavaClientCodegen extends AbstractJavaCodegen
132131
protected boolean useRxJava3 = false;
133132
// backwards compatibility for openapi configs that specify neither rx1 nor rx2
134133
// (mustache does not allow for boolean operators so we need this extra field)
135-
@Setter protected boolean doNotUseRx = true;
136-
@Setter protected boolean usePlayWS = false;
137-
@Setter protected String microprofileFramework = MICROPROFILE_DEFAULT;
138-
@Setter protected String microprofileRestClientVersion = MICROPROFILE_REST_CLIENT_DEFAULT_VERSION;
139-
@Setter protected boolean microprofileMutiny = false;
140-
@Setter protected boolean microProfileGlobalExceptionMapper = true;
141-
@Setter protected boolean microProfileRegisterExceptionMapper = true;
142-
@Setter protected String configKey = null;
143-
@Setter(AccessLevel.PRIVATE) protected boolean configKeyFromClassName = false;
144-
@Setter protected boolean asyncNative = false;
145-
@Setter protected boolean parcelableModel = false;
146-
@Setter protected boolean performBeanValidation = false;
147-
@Setter protected boolean useGzipFeature = false;
148-
@Setter protected boolean useRuntimeException = false;
149-
@Setter protected boolean useReflectionEqualsHashCode = false;
134+
@Setter
135+
protected boolean doNotUseRx = true;
136+
@Setter
137+
protected boolean usePlayWS = false;
138+
@Setter
139+
protected String microprofileFramework = MICROPROFILE_DEFAULT;
140+
@Setter
141+
protected String microprofileRestClientVersion = MICROPROFILE_REST_CLIENT_DEFAULT_VERSION;
142+
@Setter
143+
protected boolean microprofileMutiny = false;
144+
@Setter
145+
protected boolean microProfileGlobalExceptionMapper = true;
146+
@Setter
147+
protected boolean microProfileRegisterExceptionMapper = true;
148+
@Setter
149+
protected String configKey = null;
150+
@Setter(AccessLevel.PRIVATE)
151+
protected boolean configKeyFromClassName = false;
152+
@Setter
153+
protected boolean asyncNative = false;
154+
@Setter
155+
protected boolean parcelableModel = false;
156+
@Setter
157+
protected boolean performBeanValidation = false;
158+
@Setter
159+
protected boolean useGzipFeature = false;
160+
@Setter
161+
protected boolean useRuntimeException = false;
162+
@Setter
163+
protected boolean useReflectionEqualsHashCode = false;
150164
protected boolean caseInsensitiveResponseHeaders = false;
151-
@Setter protected boolean useAbstractionForFiles = false;
152-
@Setter protected boolean dynamicOperations = false;
153-
@Setter protected boolean supportStreaming = false;
154-
@Setter protected boolean withAWSV4Signature = false;
155-
@Setter protected String gradleProperties;
156-
@Setter protected String errorObjectType;
157-
@Getter @Setter protected boolean failOnUnknownProperties = false;
158-
@Setter protected boolean supportVertxFuture = false;
159-
@Setter protected boolean useSealedOneOfInterfaces = false;
160-
@Setter protected boolean useUnaryInterceptor = false;
165+
@Setter
166+
protected boolean useAbstractionForFiles = false;
167+
@Setter
168+
protected boolean dynamicOperations = false;
169+
@Setter
170+
protected boolean supportStreaming = false;
171+
@Setter
172+
protected boolean withAWSV4Signature = false;
173+
@Setter
174+
protected String gradleProperties;
175+
@Setter
176+
protected String errorObjectType;
177+
@Getter
178+
@Setter
179+
protected boolean failOnUnknownProperties = false;
180+
@Setter
181+
protected boolean supportVertxFuture = false;
182+
@Setter
183+
protected boolean useSealedOneOfInterfaces = false;
184+
@Setter
185+
protected boolean useUnaryInterceptor = false;
161186

162187
protected String authFolder;
163188
/**
164189
* Serialization library.
165190
*/
166-
@Getter protected String serializationLibrary = null;
167-
@Getter @Setter protected boolean useSpringBoot4 = false;
168-
@Getter @Setter protected boolean useJackson3 = false;
169-
@Setter protected boolean useOneOfDiscriminatorLookup = false; // use oneOf discriminator's mapping for model lookup
191+
@Getter
192+
protected String serializationLibrary = null;
193+
@Getter
194+
@Setter
195+
protected boolean useSpringBoot4 = false;
196+
@Getter
197+
@Setter
198+
protected boolean useJackson3 = false;
199+
@Setter
200+
protected boolean useOneOfDiscriminatorLookup = false; // use oneOf discriminator's mapping for model lookup
170201
protected String rootJavaEEPackage;
171202
protected Map<String, MpRestClientVersion> mpRestClientVersions = new LinkedHashMap<>();
172-
@Setter(AccessLevel.PRIVATE) protected String useSingleRequestParameter = "false";
203+
@Setter(AccessLevel.PRIVATE)
204+
protected String useSingleRequestParameter = "false";
173205
protected boolean webclientBlockingOperations = false;
174-
@Setter protected boolean generateClientAsBean = false;
175-
@Setter protected boolean useEnumCaseInsensitive = false;
206+
@Setter
207+
protected boolean generateClientAsBean = false;
208+
@Setter
209+
protected boolean useEnumCaseInsensitive = false;
176210

177-
@Setter protected int maxAttemptsForRetry = 1;
178-
@Setter protected long waitTimeMillis = 10l;
211+
@Setter
212+
protected int maxAttemptsForRetry = 1;
213+
@Setter
214+
protected long waitTimeMillis = 10l;
179215

180216
private static class MpRestClientVersion {
181217
public final String rootPackage;
@@ -280,7 +316,7 @@ public JavaClientCodegen() {
280316
supportedLibraries.put(FEIGN_HC5, "HTTP client: OpenFeign 13.2.1/HttpClient5 5.4.2. JSON processing: Jackson 2.17.1 or Gson 2.10.1");
281317
supportedLibraries.put(OKHTTP_GSON, "[DEFAULT] HTTP client: OkHttp 4.11.0. JSON processing: Gson 2.10.1. Enable Parcelable models on Android using '-DparcelableModel=true'. Enable gzip request encoding using '-DuseGzipFeature=true'.");
282318
supportedLibraries.put(RETROFIT_2, "HTTP client: OkHttp 4.11.0. JSON processing: Gson 2.10.1 (Retrofit 2.5.0) or Jackson 2.17.1. Enable the RxJava adapter using '-DuseRxJava[2/3]=true'. (RxJava 1.x or 2.x or 3.x)");
283-
supportedLibraries.put(RESTTEMPLATE, "HTTP client: Spring RestTemplate 5.3.33 (6.1.5 if `useJakartaEe=true`). JSON processing: Jackson 2.17.1");
319+
supportedLibraries.put(RESTTEMPLATE, "HTTP client: Spring RestTemplate 5.3.33 (6.2.x if `useJakartaEe=true`, 7.x.x if `useSpringBoot4=true`). JSON processing: Jackson 2.x (3.x if `useJackson3=true`)");
284320
supportedLibraries.put(WEBCLIENT, "HTTP client: Spring WebClient 5.1.18. JSON processing: Jackson 2.17.1");
285321
supportedLibraries.put(RESTCLIENT, "HTTP client: Spring RestClient 6.1.6. JSON processing: Jackson 2.17.1");
286322
supportedLibraries.put(RESTEASY, "HTTP client: Resteasy client 4.7.6. JSON processing: Jackson 2.17.1");
@@ -307,7 +343,7 @@ public JavaClientCodegen() {
307343
serializationLibrary.setEnum(serializationOptions);
308344
cliOptions.add(serializationLibrary);
309345
cliOptions.add(CliOption.newBoolean(USE_SPRING_BOOT4, "Generate code and provide dependencies for use with Spring Boot 4.x.", useSpringBoot4));
310-
cliOptions.add(CliOption.newBoolean(USE_JACKSON_3, "Set it in order to use jackson 3 dependencies (only allowed when `" + USE_SPRING_BOOT4 + "` is set and incompatible with `"+OPENAPI_NULLABLE+"`).", useJackson3)); // Ensure the OAS 3.x discriminator mappings include any descendent schemas that allOf
346+
cliOptions.add(CliOption.newBoolean(USE_JACKSON_3, "Set it in order to use jackson 3 dependencies (only allowed when `" + USE_SPRING_BOOT4 + "` is set and incompatible with `" + OPENAPI_NULLABLE + "`).", useJackson3)); // Ensure the OAS 3.x discriminator mappings include any descendent schemas that allOf
311347
// inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values,
312348
// and the discriminator mapping schemas in the OAS document.
313349
this.setLegacyDiscriminatorBehavior(false);
@@ -378,14 +414,14 @@ public void processOpts() {
378414
convertPropertyToBooleanAndWriteBack(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, this::setUseOneOfDiscriminatorLookup);
379415
convertPropertyToBooleanAndWriteBack(USE_JACKSON_3, this::setUseJackson3);
380416
convertPropertyToBooleanAndWriteBack(USE_SPRING_BOOT4, this::setUseSpringBoot4);
381-
if(isUseJackson3() && !isUseSpringBoot4()){
417+
if (isUseJackson3() && !isUseSpringBoot4()) {
382418
throw new IllegalArgumentException("useJackson3 is only available with Spring Boot >= 4");
383419
}
384-
if(isUseJackson3() && isOpenApiNullable()){
420+
if (isUseJackson3() && isOpenApiNullable()) {
385421
throw new IllegalArgumentException("openApiNullable cannot be set with useJackson3");
386422
}
387423

388-
if(this.useJackson3){
424+
if (this.useJackson3) {
389425
this.applyJackson3Package();
390426
} else {
391427
this.applyJackson2Package();

modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/ApiClient.mustache

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
package {{invokerPackage}};
44

55
{{#withXml}}
6-
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
7-
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
6+
import {{jacksonPackage}}.dataformat.xml.XmlMapper;
7+
import {{jacksonPackage}}.dataformat.xml.ser.ToXmlGenerator;
88
{{/withXml}}
99
import org.apache.commons.logging.Log;
1010
import org.apache.commons.logging.LogFactory;

modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/build.gradle.mustache

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,22 @@ ext {
115115
{{#swagger2AnnotationLibrary}}
116116
swagger_annotations_version = "2.2.9"
117117
{{/swagger2AnnotationLibrary}}
118+
{{#useJackson3}}
119+
jackson_version = "3.1.0"
120+
{{/useJackson3}}
121+
{{^useJackson3}}
118122
jackson_version = "2.21.1"
123+
{{/useJackson3}}
119124
jackson_annotations_version = "2.21"
120-
jackson_databind_version = "2.21.1"
121125
{{#openApiNullable}}
122126
jackson_databind_nullable_version = "0.2.9"
123127
{{/openApiNullable}}
128+
{{#useSpringBoot4}}
129+
spring_web_version = "7.0.5"
130+
jakarta_annotation_version = "3.0.0"
131+
bean_validation_version = "3.1.1"
132+
{{/useSpringBoot4}}
133+
{{^useSpringBoot4}}
124134
{{#useJakartaEe}}
125135
spring_web_version = "6.2.8"
126136
jakarta_annotation_version = "2.1.1"
@@ -131,6 +141,7 @@ ext {
131141
jakarta_annotation_version = "1.3.5"
132142
bean_validation_version = "2.0.2"
133143
{{/useJakartaEe}}
144+
{{/useSpringBoot4}}
134145
jodatime_version = "2.9.9"
135146
junit_version = "5.10.2"
136147
}
@@ -145,25 +156,27 @@ dependencies {
145156
implementation "com.google.code.findbugs:jsr305:3.0.2"
146157
implementation "org.springframework:spring-web:$spring_web_version"
147158
implementation "org.springframework:spring-context:$spring_web_version"
148-
implementation "com.fasterxml.jackson.core:jackson-core:$jackson_version"
159+
implementation "{{jacksonPackage}}.core:jackson-core:$jackson_version"
149160
implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_annotations_version"
150-
implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version"
161+
implementation "{{jacksonPackage}}.core:jackson-databind:$jackson_version"
151162
{{^useJakartaEe}}
152163
implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version"
153164
{{/useJakartaEe}}
154165
{{#useJakartaEe}}
155-
implementation "com.fasterxml.jackson.jakarta.rs:jackson-jakarta-rs-json-provider:$jackson_version"
166+
implementation "{{jacksonPackage}}.jakarta.rs:jackson-jakarta-rs-json-provider:$jackson_version"
156167
{{/useJakartaEe}}
157168
{{#openApiNullable}}
158169
implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version"
159170
{{/openApiNullable}}
171+
{{^useJackson3}}
160172
implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version"
173+
{{/useJackson3}}
161174
{{#joda}}
162-
implementation "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jackson_version"
175+
implementation "{{jacksonPackage}}.datatype:jackson-datatype-joda:$jackson_version"
163176
implementation "joda-time:joda-time:$jodatime_version"
164177
{{/joda}}
165178
{{#withXml}}
166-
implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version"
179+
implementation "{{jacksonPackage}}.dataformat:jackson-dataformat-xml:$jackson_version"
167180
implementation "io.github.threeten-jaxb:threeten-jaxb-core:1.2"
168181
{{/withXml}}
169182
implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version"

modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/model.mustache

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ import java.io.Serializable;
2727
{{#jackson}}
2828
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
2929
import com.fasterxml.jackson.annotation.JsonTypeName;
30+
import com.fasterxml.jackson.annotation.JsonIgnore;
3031
{{#withXml}}
31-
import com.fasterxml.jackson.dataformat.xml.annotation.*;
32+
import {{jacksonPackage}}.dataformat.xml.annotation.*;
3233
{{/withXml}}
3334
{{#vendorExtensions.x-has-readonly-properties}}
3435
import com.fasterxml.jackson.annotation.JsonCreator;

0 commit comments

Comments
 (0)