Skip to content

Commit 4b3e61f

Browse files
committed
feat(jackson3): add jackson3 support for Java Client generator - WebClient
1 parent 86b3529 commit 4b3e61f

File tree

207 files changed

+25699
-33
lines changed

Some content is hidden

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

207 files changed

+25699
-33
lines changed
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/webclient-springBoot4-jackson3
3+
library: webclient
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-webclient
8+
hideGenerationTimestamp: "true"
9+
containerDefaultToNull: "true"
10+
useSpringBoot4: true
11+
useJackson3: true
12+
openApiNullable: false

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,11 @@ public void processOpts() {
391391
this.applyJackson2Package();
392392
}
393393

394+
if(this.useSpringBoot4) {
395+
setUseJakartaEe(true);
396+
applyJakartaPackage();
397+
}
398+
394399
// override parent one
395400
importMapping.put("JsonDeserialize", (useJackson3 ? JACKSON3_PACKAGE : JACKSON2_PACKAGE) + ".databind.annotation.JsonDeserialize");
396401

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

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,21 @@
22

33
package {{invokerPackage}};
44

5+
import {{jacksonPackage}}.databind.DeserializationFeature;
6+
7+
{{#useJackson3}}
8+
import {{jacksonPackage}}.core.JacksonException;
9+
import {{jacksonPackage}}.databind.json.JsonMapper;
10+
import org.springframework.http.codec.json.JacksonJsonDecoder;
11+
import org.springframework.http.codec.json.JacksonJsonEncoder;
12+
{{/useJackson3}}
13+
{{^useJackson3}}
514
import com.fasterxml.jackson.core.JsonProcessingException;
6-
import com.fasterxml.jackson.databind.DeserializationFeature;
715
import com.fasterxml.jackson.databind.ObjectMapper;
816
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
17+
import org.springframework.http.codec.json.Jackson2JsonDecoder;
18+
import org.springframework.http.codec.json.Jackson2JsonEncoder;
19+
{{/useJackson3}}
920
{{#openApiNullable}}
1021
import org.openapitools.jackson.nullable.JsonNullableModule;
1122
{{/openApiNullable}}
@@ -27,8 +38,6 @@ import org.springframework.http.client.ClientHttpRequestExecution;
2738
import org.springframework.http.client.ClientHttpRequestInterceptor;
2839
import org.springframework.http.client.ClientHttpResponse;
2940
import org.springframework.http.client.reactive.ClientHttpRequest;
30-
import org.springframework.http.codec.json.Jackson2JsonDecoder;
31-
import org.springframework.http.codec.json.Jackson2JsonEncoder;
3241
{{#generateClientAsBean}}
3342
import org.springframework.stereotype.Component;
3443
{{/generateClientAsBean}}
@@ -110,15 +119,20 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
110119

111120
protected final WebClient webClient;
112121
protected final DateFormat dateFormat;
113-
protected final ObjectMapper objectMapper;
122+
{{^useJackson3}}
123+
protected final ObjectMapper mapper;
124+
{{/useJackson3}}
125+
{{#useJackson3}}
126+
protected final JsonMapper mapper;
127+
{{/useJackson3}}
114128

115129
protected Map<String, Authentication> authentications;
116130

117131

118132
public ApiClient() {
119133
this.dateFormat = createDefaultDateFormat();
120-
this.objectMapper = createDefaultObjectMapper(this.dateFormat);
121-
this.webClient = buildWebClient(this.objectMapper);
134+
this.mapper = createDefaultMapper(this.dateFormat);
135+
this.webClient = buildWebClient(this.mapper);
122136
this.init();
123137
}
124138

@@ -129,18 +143,18 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
129143
this(Optional.ofNullable(webClient).orElseGet(() -> buildWebClient()), createDefaultDateFormat());
130144
}
131145

132-
public ApiClient(ObjectMapper mapper, DateFormat format) {
133-
this(buildWebClient(mapper.copy()), format);
146+
public ApiClient({{#useJackson3}}JsonMapper{{/useJackson3}}{{^useJackson3}}ObjectMapper{{/useJackson3}} mapper, DateFormat format) {
147+
this(buildWebClient(mapper), format);
134148
}
135149

136-
public ApiClient(WebClient webClient, ObjectMapper mapper, DateFormat format) {
137-
this(Optional.ofNullable(webClient).orElseGet(() -> buildWebClient(mapper.copy())), format);
150+
public ApiClient(WebClient webClient, {{#useJackson3}}JsonMapper{{/useJackson3}}{{^useJackson3}}ObjectMapper{{/useJackson3}} mapper, DateFormat format) {
151+
this(Optional.ofNullable(webClient).orElseGet(() -> buildWebClient(mapper)), format);
138152
}
139153

140154
protected ApiClient(WebClient webClient, DateFormat format) {
141155
this.webClient = webClient;
142156
this.dateFormat = format;
143-
this.objectMapper = createDefaultObjectMapper(format);
157+
this.mapper = createDefaultMapper(format);
144158
this.init();
145159
}
146160

@@ -150,7 +164,21 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
150164
return dateFormat;
151165
}
152166

153-
public static ObjectMapper createDefaultObjectMapper(@Nullable DateFormat dateFormat) {
167+
{{#useJackson3}}
168+
public static JsonMapper createDefaultMapper(@Nullable DateFormat dateFormat) {
169+
return JsonMapper.builder()
170+
.defaultDateFormat(dateFormat)
171+
{{#failOnUnknownProperties}}
172+
.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
173+
{{/failOnUnknownProperties}}
174+
{{^failOnUnknownProperties}}
175+
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
176+
{{/failOnUnknownProperties}}
177+
.build();
178+
}
179+
{{/useJackson3}}
180+
{{^useJackson3}}
181+
public static ObjectMapper createDefaultMapper(@Nullable DateFormat dateFormat) {
154182
if (null == dateFormat) {
155183
dateFormat = createDefaultDateFormat();
156184
}
@@ -164,6 +192,8 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
164192
{{/openApiNullable}}
165193
return mapper;
166194
}
195+
{{/useJackson3}}
196+
167197

168198
protected void init() {
169199
// Setup authentications (key: authentication name, value: authentication).
@@ -181,12 +211,18 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
181211
* @param mapper ObjectMapper used for serialize/deserialize
182212
* @return WebClient
183213
*/
184-
public static WebClient.Builder buildWebClientBuilder(ObjectMapper mapper) {
214+
public static WebClient.Builder buildWebClientBuilder({{#useJackson3}}JsonMapper{{/useJackson3}}{{^useJackson3}}ObjectMapper{{/useJackson3}} mapper) {
185215
ExchangeStrategies strategies = ExchangeStrategies
186216
.builder()
187217
.codecs(clientDefaultCodecsConfigurer -> {
218+
{{#useJackson3}}
219+
clientDefaultCodecsConfigurer.defaultCodecs().jacksonJsonEncoder(new JacksonJsonEncoder(mapper, MediaType.APPLICATION_JSON));
220+
clientDefaultCodecsConfigurer.defaultCodecs().jacksonJsonDecoder(new JacksonJsonDecoder(mapper, MediaType.APPLICATION_JSON));
221+
{{/useJackson3}}
222+
{{^useJackson3}}
188223
clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(mapper, MediaType.APPLICATION_JSON));
189224
clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(mapper, MediaType.APPLICATION_JSON));
225+
{{/useJackson3}}
190226
}).build();
191227
WebClient.Builder webClientBuilder = WebClient.builder().exchangeStrategies(strategies);
192228
return webClientBuilder;
@@ -197,15 +233,15 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
197233
* @return WebClient
198234
*/
199235
public static WebClient.Builder buildWebClientBuilder() {
200-
return buildWebClientBuilder(createDefaultObjectMapper(null));
236+
return buildWebClientBuilder(createDefaultMapper(null));
201237
}
202238

203239
/**
204240
* Build the WebClient used to make HTTP requests.
205241
* @param mapper ObjectMapper used for serialize/deserialize
206242
* @return WebClient
207243
*/
208-
public static WebClient buildWebClient(ObjectMapper mapper) {
244+
public static WebClient buildWebClient({{#useJackson3}}JsonMapper{{/useJackson3}}{{^useJackson3}}ObjectMapper{{/useJackson3}} mapper) {
209245
return buildWebClientBuilder(mapper).build();
210246
}
211247

@@ -214,7 +250,7 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
214250
* @return WebClient
215251
*/
216252
public static WebClient buildWebClient() {
217-
return buildWebClientBuilder(createDefaultObjectMapper(null)).build();
253+
return buildWebClientBuilder(createDefaultMapper(null)).build();
218254
}
219255

220256
/**
@@ -403,11 +439,11 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
403439
}
404440

405441
/**
406-
* Get the ObjectMapper used to make HTTP requests.
407-
* @return ObjectMapper objectMapper
442+
* Get the {{#useJackson3}}JsonMapper{{/useJackson3}}{{^useJackson3}}ObjectMapper{{/useJackson3}} used to make HTTP requests.
443+
* @return {{#useJackson3}}JsonMapper{{/useJackson3}}{{^useJackson3}}ObjectMapper{{/useJackson3}} mapper
408444
*/
409-
public ObjectMapper getObjectMapper() {
410-
return objectMapper;
445+
public {{#useJackson3}}JsonMapper{{/useJackson3}}{{^useJackson3}}ObjectMapper{{/useJackson3}} get{{#useJackson3}}JsonMapper{{/useJackson3}}{{^useJackson3}}ObjectMapper{{/useJackson3}}() {
446+
return mapper;
411447
}
412448

413449
/**
@@ -457,17 +493,17 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
457493
valueCollection = (Collection<?>) value;
458494
} else {
459495
try {
460-
return parameterToMultiValueMap(collectionFormat, name, objectMapper.writeValueAsString(value));
461-
} catch (JsonProcessingException e) {
496+
return parameterToMultiValueMap(collectionFormat, name, mapper.writeValueAsString(value));
497+
} catch ({{#useJackson3}}JacksonException{{/useJackson3}}{{^useJackson3}}JsonProcessingException{{/useJackson3}} e) {
462498
throw new RuntimeException(e);
463499
}
464500
}
465501

466502
List<String> values = new ArrayList<>();
467503
for(Object o : valueCollection) {
468504
try {
469-
values.add(objectMapper.writeValueAsString(o));
470-
} catch (JsonProcessingException e) {
505+
values.add(mapper.writeValueAsString(o));
506+
} catch ({{#useJackson3}}JacksonException{{/useJackson3}}{{^useJackson3}}JsonProcessingException{{/useJackson3}} e) {
471507
throw new RuntimeException(e);
472508
}
473509
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import java.io.Serializable;
2828
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
2929
import com.fasterxml.jackson.annotation.JsonTypeName;
3030
{{#withXml}}
31-
import com.fasterxml.jackson.dataformat.xml.annotation.*;
31+
import {{jacksonPackage}}.dataformat.xml.annotation.*;
3232
{{/withXml}}
3333
{{#vendorExtensions.x-has-readonly-properties}}
3434
import com.fasterxml.jackson.annotation.JsonCreator;

modules/openapi-generator/src/main/resources/Java/libraries/webclient/pom.mustache

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,25 @@
114114
</dependency>
115115

116116
<!-- JSON processing: jackson -->
117+
<dependency>
118+
<groupId>{{jacksonPackage}}.core</groupId>
119+
<artifactId>jackson-core</artifactId>
120+
<version>${jackson-version}</version>
121+
</dependency>
117122
<dependency>
118123
<groupId>com.fasterxml.jackson.core</groupId>
124+
<artifactId>jackson-annotations</artifactId>
125+
<version>${jackson-annotations-version}</version>
126+
</dependency>
127+
<dependency>
128+
<groupId>{{jacksonPackage}}.core</groupId>
119129
<artifactId>jackson-databind</artifactId>
120-
<version>${jackson-databind-version}</version>
130+
<version>${jackson-version}</version>
131+
</dependency>
132+
<dependency>
133+
<groupId>{{jacksonPackage}}.jakarta.rs</groupId>
134+
<artifactId>jackson-jakarta-rs-json-provider</artifactId>
135+
<version>${jackson-version}</version>
121136
</dependency>
122137
{{#openApiNullable}}
123138
<dependency>
@@ -127,14 +142,16 @@
127142
</dependency>
128143
{{/openApiNullable}}
129144

145+
{{^useJackson3}}
130146
<dependency>
131147
<groupId>com.fasterxml.jackson.datatype</groupId>
132148
<artifactId>jackson-datatype-jsr310</artifactId>
133149
<version>${jackson-version}</version>
134150
</dependency>
151+
{{/useJackson3}}
135152
{{#joda}}
136153
<dependency>
137-
<groupId>com.fasterxml.jackson.datatype</groupId>
154+
<groupId>{{jacksonPackage}}.datatype</groupId>
138155
<artifactId>jackson-datatype-joda</artifactId>
139156
<version>${jackson-version}</version>
140157
</dependency>
@@ -162,18 +179,27 @@
162179
<properties>
163180
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
164181
{{#swagger1AnnotationLibrary}}
165-
<swagger-annotations-version>1.6.6</swagger-annotations-version>
182+
<swagger-annotations-version>1.6.16</swagger-annotations-version>
166183
{{/swagger1AnnotationLibrary}}
167184
{{#swagger2AnnotationLibrary}}
168-
<swagger-annotations-version>2.2.15</swagger-annotations-version>
185+
<swagger-annotations-version>2.2.43</swagger-annotations-version>
169186
{{/swagger2AnnotationLibrary}}
170-
<jackson-version>2.19.2</jackson-version>
171-
<jackson-databind-version>2.19.2</jackson-databind-version>
187+
{{#useJackson3}}
188+
<jackson-version>3.0.4</jackson-version>
189+
{{/useJackson3}}
190+
{{^useJackson3}}
191+
<jackson-version>2.21.0</jackson-version>
192+
{{/useJackson3}}
172193
{{#openApiNullable}}
173194
<jackson-databind-nullable-version>0.2.9</jackson-databind-nullable-version>
174195
{{/openApiNullable}}
175196
{{#useJakartaEe}}
197+
{{^useSpringBoot4}}
176198
<spring-boot-version>3.2.12</spring-boot-version>
199+
{{/useSpringBoot4}}
200+
{{#useSpringBoot4}}
201+
<spring-boot-version>4.0.2</spring-boot-version>
202+
{{/useSpringBoot4}}
177203
<jakarta-annotation-version>2.1.1</jakarta-annotation-version>
178204
<reactor-version>3.5.12</reactor-version>
179205
<reactor-netty-version>1.2.8</reactor-netty-version>
@@ -184,9 +210,10 @@
184210
<reactor-version>3.4.34</reactor-version>
185211
<reactor-netty-version>1.2.8</reactor-netty-version>
186212
{{/useJakartaEe}}
187-
<junit-version>5.10.2</junit-version>
213+
<jackson-annotations-version>2.21</jackson-annotations-version>
214+
<junit-version>5.14.3</junit-version>
188215
{{#joda}}
189-
<jodatime-version>2.9.9</jodatime-version>
216+
<jodatime-version>2.14.0</jodatime-version>
190217
{{/joda}}
191218
</properties>
192219
</project>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
2+
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
3+
#
4+
# This file is auto-generated by OpenAPI Generator (https://openapi-generator.tech)
5+
6+
name: Java CI with Maven
7+
8+
on:
9+
push:
10+
branches: [ main, master ]
11+
pull_request:
12+
branches: [ main, master ]
13+
14+
jobs:
15+
build:
16+
name: Build OpenAPI Petstore
17+
runs-on: ubuntu-latest
18+
strategy:
19+
matrix:
20+
java: [ 17, 21 ]
21+
steps:
22+
- uses: actions/checkout@v4
23+
- name: Set up JDK
24+
uses: actions/setup-java@v4
25+
with:
26+
java-version: ${{ matrix.java }}
27+
distribution: 'temurin'
28+
cache: maven
29+
- name: Build with Maven
30+
run: mvn -B package --no-transfer-progress --file pom.xml
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
*.class
2+
3+
# Mobile Tools for Java (J2ME)
4+
.mtj.tmp/
5+
6+
# Package Files #
7+
*.jar
8+
*.war
9+
*.ear
10+
11+
# exclude jar for gradle wrapper
12+
!gradle/wrapper/*.jar
13+
14+
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
15+
hs_err_pid*
16+
17+
# build files
18+
**/target
19+
target
20+
.gradle
21+
build
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# OpenAPI Generator Ignore
2+
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
3+
4+
# Use this file to prevent files from being overwritten by the generator.
5+
# The patterns follow closely to .gitignore or .dockerignore.
6+
7+
# As an example, the C# client generator defines ApiClient.cs.
8+
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
9+
#ApiClient.cs
10+
11+
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
12+
#foo/*/qux
13+
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
14+
15+
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
16+
#foo/**/qux
17+
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
18+
19+
# You can also negate patterns with an exclamation (!).
20+
# For example, you can ignore all files in a docs folder with the file extension .md:
21+
#docs/*.md
22+
# Then explicitly reverse the ignore rule for a single file:
23+
#!docs/README.md

0 commit comments

Comments
 (0)