Skip to content

Commit c277176

Browse files
authored
chore: upgrade to openapi generator 7.11 (#2517)
Upgraded to openapi generator version 7.11. One of our issues was fixed in this version but we got two new issues back for which I added workarounds.. It looks like both are caused by the new support for JSON-B polymorphism type annotations introduced by OpenAPITools/openapi-generator#20164: Solves PZ-5160
1 parent efe56a4 commit c277176

File tree

9 files changed

+217
-82
lines changed

9 files changed

+217
-82
lines changed

build.gradle.kts

+6-4
Original file line numberDiff line numberDiff line change
@@ -517,12 +517,15 @@ tasks {
517517
"sourceFolder" to "",
518518
"dateLibrary" to "java8",
519519
"disallowAdditionalPropertiesIfNotPresent" to "false",
520-
"openApiNullable" to "false",
521520
"useJakartaEe" to "true"
522521
)
523522
)
524-
// Specify custom Mustache template dir as temporary workaround for the issue where OpenAPI Generator
525-
// fails to generate import statements for @JsonbCreator annotations.
523+
// Specify custom Mustache template dir as temporary workaround for issues we have with the OpenAPI Generator.
524+
// Both issues have to do with the support for JSON-B polymorphism type annotations introduced by
525+
// https://github.com/OpenAPITools/openapi-generator/pull/20164 in OpenAPI Generator version 7.11.
526+
// Instead of overriding these Mustache templates the obvious workaround seems to set the additional property
527+
// 'jsonbPolymorphism' to false in this Gradle build file. However, that does not seem to work.
528+
// Probably because this property is set by the OpenAPI Generator library itself regardless of our configuration.
526529
templateDir.set("$rootDir/src/main/resources/openapi-generator-templates")
527530
}
528531

@@ -568,7 +571,6 @@ tasks {
568571
"sourceFolder" to "",
569572
"dateLibrary" to "java8-localdatetime",
570573
"disallowAdditionalPropertiesIfNotPresent" to "false",
571-
"openApiNullable" to "false",
572574
"useJakartaEe" to "true"
573575
)
574576
)

gradle/libs.versions.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ nodejs = "20.17.0"
55
jsonschema2pojo = "1.2.2"
66
kotlin-csv = "1.10.0"
77
openapi = "4.0.7"
8-
openapi-generator = "7.10.0"
8+
openapi-generator = "7.11.0"
99
opentelemetry = "1.46.0"
1010
opentelemetry-instrumentation = "2.12.0"
1111
node-gradle = "7.1.0"

src/itest/kotlin/nl/info/zac/itest/KlantRestServiceTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ class KlantRestServiceTest : BehaviorSpec({
8686
the response should be a 200 HTTP response with personal data from both the BRP and Klanten databases
8787
"""
8888
) {
89-
response.code shouldBe HTTP_STATUS_OK
9089
val responseBody = response.body!!.string()
9190
logger.info { "Response: $responseBody" }
91+
response.code shouldBe HTTP_STATUS_OK
9292
responseBody shouldEqualJson """
9393
{
9494
"bsn": "$TEST_PERSON_HENDRIKA_JANSE_BSN",

src/main/java/net/atos/zac/app/bag/converter/RESTBAGConverter.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
import org.apache.commons.lang3.StringUtils;
1717

1818
import net.atos.client.bag.model.generated.PointGeoJSON;
19-
import net.atos.client.bag.model.generated.PolygonGeoJSON;
2019
import net.atos.client.bag.model.generated.PuntOfVlak;
20+
import net.atos.client.bag.model.generated.Surface;
2121
import net.atos.client.zgw.zrc.model.Zaak;
2222
import net.atos.client.zgw.zrc.model.zaakobjecten.Zaakobject;
2323
import net.atos.client.zgw.zrc.model.zaakobjecten.ZaakobjectAdres;
@@ -95,11 +95,11 @@ public static String getHuisnummerWeergave(final Integer huisnummer, final Strin
9595
return volledigHuisnummer.toString().trim();
9696
}
9797

98-
public static RestGeometry convertVlak(final PolygonGeoJSON polygonGeoJSON) {
98+
public static RestGeometry convertVlak(final Surface surface) {
9999
return new RestGeometry(
100-
polygonGeoJSON.getType().value(),
100+
surface.getType().value(),
101101
null,
102-
polygonGeoJSON.getCoordinates()
102+
surface.getCoordinates()
103103
.stream()
104104
.map(coords -> coords.stream()
105105
.map(RESTBAGConverter::convertCoordinates)

src/main/resources/openapi-generator-templates/model.mustache

-64
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
{{! Lifely/INFO temporary workaround for the issue where the OpenAPI Generator Gradle plugin }}
2+
{{! incorrectly generates '@JsonbTransient' annotations for certain 'type' fields in polymorphic model classes }}
3+
{{! which has the result that these fields are not serialized and deserialized leading to errors in the various APIs we use. }}
4+
{{! For example in the generated BRP 'PersonenQuery.java' class the 'type' String field was given the '@JsonbTransient' annotation }}
5+
{{! which breaks the ZAC BRP API integration because this is mandatory field in the BRP API. }}
6+
{{! This was most likely introduced by: https://github.com/OpenAPITools/openapi-generator/pull/20164 }}
7+
{{! It may also be that the BRP OpenAPI spec does not use the discriminator keyword correctly since these 'type' fields are simple strings. }}
8+
{{! and not polymorphic structures. Also see: https://apidog.com/blog/openapi-discriminator-guide/ }}
9+
10+
{{! This template is based on a copy of the Java Mustache model template of the main branch of https://github.com/OpenAPITools/openapi-generator }}
11+
{{! This workaround can be removed once we have migrated to a version of the OpenAPI Generator Gradle plugin that has solved this issue. }}
12+
13+
{{#withXml}}
14+
{{#hasVars}}@XmlType(name = "{{classname}}", propOrder =
15+
{ {{#vars}}"{{name}}"{{^-last}}, {{/-last}}{{/vars}} }
16+
){{/hasVars}}
17+
{{^hasVars}}@XmlType(name = "{{classname}}"){{/hasVars}}
18+
{{> xmlAnnotation }}
19+
{{/withXml}}
20+
{{#jackson}}
21+
@JsonPropertyOrder({
22+
{{#vars}}
23+
{{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}}
24+
{{/vars}}
25+
})
26+
{{#isClassnameSanitized}}
27+
{{^hasDiscriminatorWithNonEmptyMapping}}
28+
@JsonTypeName("{{name}}")
29+
{{/hasDiscriminatorWithNonEmptyMapping}}
30+
{{/isClassnameSanitized}}
31+
{{/jackson}}
32+
{{#description}}
33+
/**
34+
* {{{.}}}
35+
*/
36+
{{/description}}
37+
{{>additionalModelTypeAnnotations}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}
38+
{{#vendorExtensions.x-class-extra-annotation}}
39+
{{{vendorExtensions.x-class-extra-annotation}}}
40+
{{/vendorExtensions.x-class-extra-annotation}}
41+
public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}}{{#vendorExtensions.x-implements}}{{#-first}} implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} {
42+
{{#vars}}{{#isEnum}}{{^isContainer}}
43+
{{>enumClass}}{{/isContainer}}{{#isContainer}}{{#mostInnerItems}}
44+
{{>enumClass}}{{/mostInnerItems}}{{/isContainer}}{{/isEnum}}
45+
{{#jackson}}
46+
public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}";
47+
{{/jackson}}
48+
{{#withXml}}
49+
@Xml{{#isXmlAttribute}}Attribute{{/isXmlAttribute}}{{^isXmlAttribute}}Element{{/isXmlAttribute}}(name = "{{items.xmlName}}{{^items.xmlName}}{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}{{/items.xmlName}}"{{#xmlNamespace}}, namespace = "{{.}}"{{/xmlNamespace}})
50+
{{#isXmlWrapped}}
51+
@XmlElementWrapper(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}"{{#xmlNamespace}}, namespace = "{{.}}"{{/xmlNamespace}})
52+
{{/isXmlWrapped}}
53+
{{/withXml}}
54+
{{#description}}
55+
/**
56+
* {{{.}}}
57+
*/
58+
{{/description}}
59+
{{^withXml}}
60+
{{! Lifely/INFO. Changed this line to prevent the generation of the @JsonbTransient annotation for polymorphism. See reasons above. }}
61+
{{#jsonb}}@JsonbProperty("{{baseName}}"){{/jsonb}}
62+
{{! Lifely/INFO. End of change. }}
63+
{{/withXml}}
64+
{{#vendorExtensions.x-field-extra-annotation}}
65+
{{{vendorExtensions.x-field-extra-annotation}}}
66+
{{/vendorExtensions.x-field-extra-annotation}}
67+
{{#isContainer}}
68+
private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}};
69+
{{/isContainer}}
70+
{{^isContainer}}
71+
private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
72+
{{/isContainer}}
73+
{{/vars}}
74+
{{#vendorExtensions.x-has-readonly-properties}}{{^withXml}}
75+
public {{classname}}() {
76+
}
77+
78+
{{#jsonb}}@JsonbCreator{{/jsonb}}{{#jackson}}@JsonCreator{{/jackson}}
79+
public {{classname}}(
80+
{{#readOnlyVars}}
81+
{{#jsonb}}@JsonbProperty(value = "{{baseName}}"{{^required}}, nillable = true{{/required}}){{/jsonb}}{{#jackson}}@JsonProperty(value = JSON_PROPERTY_{{nameInSnakeCase}}{{#required}}, required = true{{/required}}){{/jackson}} {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}}
82+
{{/readOnlyVars}}
83+
) {
84+
{{#readOnlyVars}}
85+
this.{{name}} = {{name}};
86+
{{/readOnlyVars}}
87+
}
88+
{{/withXml}}{{/vendorExtensions.x-has-readonly-properties}}
89+
{{#vars}}
90+
/**
91+
{{#description}}
92+
* {{.}}
93+
{{/description}}
94+
{{^description}}
95+
* Get {{name}}
96+
{{/description}}
97+
{{#minimum}}
98+
* minimum: {{.}}
99+
{{/minimum}}
100+
{{#maximum}}
101+
* maximum: {{.}}
102+
{{/maximum}}
103+
* @return {{name}}
104+
{{#deprecated}}
105+
* @deprecated
106+
{{/deprecated}}
107+
**/
108+
{{#deprecated}}
109+
@Deprecated
110+
{{/deprecated}}
111+
{{#vendorExtensions.x-extra-annotation}}
112+
{{{vendorExtensions.x-extra-annotation}}}
113+
{{/vendorExtensions.x-extra-annotation}}
114+
{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}}{{#jackson}}{{> jackson_annotations}}{{/jackson}} {{#withXml}}{{#isEnum}}{{^isArray}}{{^isMap}} public {{dataType}} {{getter}}() {
115+
if ({{name}} == null) {
116+
return null;
117+
}
118+
return {{name}}.value();
119+
}{{/isMap}}{{/isArray}}{{/isEnum}}{{/withXml}}{{^withXml}}{{#isEnum}}{{^isArray}}{{^isMap}}public {{datatypeWithEnum}} {{getter}}() {
120+
return {{name}};
121+
}{{/isMap}}{{/isArray}}{{/isEnum}}{{/withXml}}{{#isEnum}}{{#isArray}}public {{{datatypeWithEnum}}} {{getter}}() {
122+
return {{name}};
123+
}{{/isArray}}{{/isEnum}}{{#isEnum}}{{#isMap}}public {{{datatypeWithEnum}}} {{getter}}() {
124+
return {{name}};
125+
}{{/isMap}}{{/isEnum}}{{^isEnum}}public {{{datatypeWithEnum}}} {{getter}}() {
126+
return {{name}};
127+
}{{/isEnum}}
128+
129+
{{^isReadOnly}}
130+
/**
131+
* Set {{name}}
132+
*/
133+
{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}}
134+
{{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{> jackson_annotations}}{{/jackson}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) {
135+
this.{{name}} = {{name}};
136+
}
137+
138+
public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) {
139+
this.{{name}} = {{name}};
140+
return this;
141+
}
142+
{{#isArray}}
143+
144+
public {{classname}} add{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
145+
if (this.{{name}} == null) {
146+
this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}};
147+
}
148+
this.{{name}}.add({{name}}Item);
149+
return this;
150+
}
151+
{{/isArray}}
152+
{{#isMap}}
153+
154+
public {{classname}} put{{nameInPascalCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
155+
if (this.{{name}} == null) {
156+
this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}};
157+
}
158+
this.{{name}}.put(key, {{name}}Item);
159+
return this;
160+
}
161+
{{/isMap}}
162+
{{/isReadOnly}}
163+
164+
{{/vars}}
165+
{{>pojoOverrides}}
166+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{{! Lifely/INFO temporary workaround for the issue where the OpenAPI Generator Gradle plugin }}
2+
{{! generates '@JsonbTypeInfo(key = "type")' annotations in the generated model classes both for }}
3+
{{! parent and child polymorphic classes resulting in errors such as: }}
4+
{{! "Caused by: jakarta.json.bind.JsonbException: One polymorphic chain cannot have two conflicting property names. }}
5+
{{! Polymorphic type defined on the type net.atos.client.bag.model.generated.Standplaats }}
6+
{{! and net.atos.client.bag.model.generated.AdresseerbaarObject have conflicting property name" }}
7+
{{! This was most likely introduced by: https://github.com/OpenAPITools/openapi-generator/pull/20164 }}
8+
9+
{{! This template is based on a copy of the Java Mustache model template of the main branch of https://github.com/OpenAPITools/openapi-generator }}
10+
{{! This workaround can be removed once we have migrated to a version of the OpenAPI Generator Gradle plugin that has solved this issue. }}
11+
12+
{{#jackson}}
13+
14+
@JsonIgnoreProperties(
15+
value = "{{{discriminator.propertyBaseName}}}", // ignore manually set {{{discriminator.propertyBaseName}}}, it will be automatically generated by Jackson during serialization
16+
allowSetters = true // allows the {{{discriminator.propertyBaseName}}} to be set during deserialization
17+
)
18+
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminator.propertyBaseName}}}", visible = true)
19+
{{#discriminator.mappedModels}}
20+
{{#-first}}
21+
@JsonSubTypes({
22+
{{/-first}}
23+
@JsonSubTypes.Type(value = {{modelName}}.class, name = "{{^vendorExtensions.x-discriminator-value}}{{mappingName}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"),
24+
{{#-last}}
25+
})
26+
{{/-last}}
27+
{{/discriminator.mappedModels}}
28+
{{/jackson}}
29+
{{#jsonbPolymorphism}}
30+
{{! Workaround Lifely/INFO: the original code has been removed for reasons see above }}
31+
{{/jsonbPolymorphism}}

src/test/kotlin/net/atos/zac/app/bag/BagFixtures.kt

+5-5
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ import net.atos.client.bag.model.generated.AdresseerbaarObjectIOHal
99
import net.atos.client.bag.model.generated.Ligplaats
1010
import net.atos.client.bag.model.generated.LigplaatsIOHal
1111
import net.atos.client.bag.model.generated.PointGeoJSON
12-
import net.atos.client.bag.model.generated.PolygonGeoJSON
1312
import net.atos.client.bag.model.generated.PuntOfVlak
1413
import net.atos.client.bag.model.generated.Standplaats
1514
import net.atos.client.bag.model.generated.StandplaatsIOHal
1615
import net.atos.client.bag.model.generated.StatusPlaats
1716
import net.atos.client.bag.model.generated.StatusVerblijfsobject
17+
import net.atos.client.bag.model.generated.Surface
1818
import net.atos.client.bag.model.generated.Verblijfsobject
1919
import net.atos.client.bag.model.generated.VerblijfsobjectIOHal
2020
import java.math.BigDecimal
@@ -24,7 +24,7 @@ fun createLigplaatsAdresseerbaarObject(status: StatusPlaats) =
2424
ligplaats = LigplaatsIOHal().apply {
2525
ligplaats = Ligplaats().apply {
2626
this.status = status
27-
this.geometrie = createPolygonGeoJSON()
27+
this.geometrie = createSurface()
2828
}
2929
}
3030
}
@@ -34,7 +34,7 @@ fun createStandplaatsAdresseerbaarObject(status: StatusPlaats) =
3434
standplaats = StandplaatsIOHal().apply {
3535
standplaats = Standplaats().apply {
3636
this.status = status
37-
this.geometrie = createPolygonGeoJSON()
37+
this.geometrie = createSurface()
3838
}
3939
}
4040
}
@@ -56,8 +56,8 @@ fun createPuntOfVlak() = PuntOfVlak().apply {
5656
}
5757
}
5858

59-
fun createPolygonGeoJSON() = PolygonGeoJSON().apply {
60-
type = PolygonGeoJSON.TypeEnum.POLYGON
59+
fun createSurface() = Surface().apply {
60+
type = Surface.TypeEnum.POLYGON
6161
coordinates = listOf(listOf(createCoordinates())) as List<List<List<BigDecimal?>?>?>?
6262
}
6363

0 commit comments

Comments
 (0)