Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/samples-jdk17.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ on:
- samples/server/petstore/java-helidon-server/v3/se/**
- samples/server/petstore/jaxrs-spec-sealed/**
- samples/server/petstore/jaxrs-spec-records/**
- samples/server/petstore/jaxrs-spec-records-helidon/**
- samples/server/petstore/jaxrs-spec-records-kumuluzee/**
- samples/server/petstore/jaxrs-spec-records-openliberty/**
- samples/server/petstore/jaxrs-spec-records-quarkus/**
- samples/server/petstore/jaxrs-spec-records-thorntail/**
pull_request:
paths:
# clients
Expand All @@ -48,6 +53,11 @@ on:
- samples/server/petstore/java-helidon-server/v3/se/**
- samples/server/petstore/jaxrs-spec-sealed/**
- samples/server/petstore/jaxrs-spec-records/**
- samples/server/petstore/jaxrs-spec-records-helidon/**
- samples/server/petstore/jaxrs-spec-records-kumuluzee/**
- samples/server/petstore/jaxrs-spec-records-openliberty/**
- samples/server/petstore/jaxrs-spec-records-quarkus/**
- samples/server/petstore/jaxrs-spec-records-thorntail/**
jobs:
build:
name: Build with JDK17
Expand Down Expand Up @@ -78,6 +88,11 @@ jobs:
- samples/server/petstore/java-helidon-server/v3/se
- samples/server/petstore/jaxrs-spec-sealed
- samples/server/petstore/jaxrs-spec-records
- samples/server/petstore/jaxrs-spec-records-helidon
- samples/server/petstore/jaxrs-spec-records-kumuluzee
- samples/server/petstore/jaxrs-spec-records-openliberty
- samples/server/petstore/jaxrs-spec-records-quarkus
- samples/server/petstore/jaxrs-spec-records-thorntail
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
Expand Down
11 changes: 11 additions & 0 deletions bin/configs/jaxrs-spec-records-helidon.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
generatorName: jaxrs-spec
outputDir: samples/server/petstore/jaxrs-spec-records-helidon
library: helidon
inputSpec: modules/openapi-generator/src/test/resources/3_0/jaxrs-spec/oneof_interface.yaml
templateDir: modules/openapi-generator/src/main/resources/JavaJaxRS/spec
additionalProperties:
artifactId: jaxrs-spec-records-helidon-petstore-server
useOneOfInterfaces: "true"
useSealed: "true"
useRecords: "true"
hideGenerationTimestamp: "true"
15 changes: 15 additions & 0 deletions bin/configs/jaxrs-spec-records-kumuluzee.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
generatorName: jaxrs-spec
outputDir: samples/server/petstore/jaxrs-spec-records-kumuluzee
library: kumuluzee
inputSpec: modules/openapi-generator/src/test/resources/3_0/jaxrs-spec/oneof_interface.yaml
templateDir: modules/openapi-generator/src/main/resources/JavaJaxRS/spec
additionalProperties:
artifactId: jaxrs-spec-records-kumuluzee-petstore-server
useOneOfInterfaces: "true"
useSealed: "true"
useRecords: "true"
hideGenerationTimestamp: "true"
# This library's pom does not ship jackson-databind-nullable, and the pojo
# template imports JsonNullable whenever openApiNullable is on (the default),
# so the sample would not compile. Unrelated to records; see PetBase.
openApiNullable: "false"
15 changes: 15 additions & 0 deletions bin/configs/jaxrs-spec-records-openliberty.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
generatorName: jaxrs-spec
outputDir: samples/server/petstore/jaxrs-spec-records-openliberty
library: openliberty
inputSpec: modules/openapi-generator/src/test/resources/3_0/jaxrs-spec/oneof_interface.yaml
templateDir: modules/openapi-generator/src/main/resources/JavaJaxRS/spec
additionalProperties:
artifactId: jaxrs-spec-records-openliberty-petstore-server
useOneOfInterfaces: "true"
useSealed: "true"
useRecords: "true"
hideGenerationTimestamp: "true"
# This library's pom does not ship jackson-databind-nullable, and the pojo
# template imports JsonNullable whenever openApiNullable is on (the default),
# so the sample would not compile. Unrelated to records; see PetBase.
openApiNullable: "false"
11 changes: 11 additions & 0 deletions bin/configs/jaxrs-spec-records-quarkus.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
generatorName: jaxrs-spec
outputDir: samples/server/petstore/jaxrs-spec-records-quarkus
library: quarkus
inputSpec: modules/openapi-generator/src/test/resources/3_0/jaxrs-spec/oneof_interface.yaml
templateDir: modules/openapi-generator/src/main/resources/JavaJaxRS/spec
additionalProperties:
artifactId: jaxrs-spec-records-quarkus-petstore-server
useOneOfInterfaces: "true"
useSealed: "true"
useRecords: "true"
hideGenerationTimestamp: "true"
15 changes: 15 additions & 0 deletions bin/configs/jaxrs-spec-records-thorntail.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
generatorName: jaxrs-spec
outputDir: samples/server/petstore/jaxrs-spec-records-thorntail
library: thorntail
inputSpec: modules/openapi-generator/src/test/resources/3_0/jaxrs-spec/oneof_interface.yaml
templateDir: modules/openapi-generator/src/main/resources/JavaJaxRS/spec
additionalProperties:
artifactId: jaxrs-spec-records-thorntail-petstore-server
useOneOfInterfaces: "true"
useSealed: "true"
useRecords: "true"
hideGenerationTimestamp: "true"
# This library's pom does not ship jackson-databind-nullable, and the pojo
# template imports JsonNullable whenever openApiNullable is on (the default),
# so the sample would not compile. Unrelated to records; see PetBase.
openApiNullable: "false"
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,22 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
}
if (useRecords && useSealed && isOneOfInterfaceRecordCandidate(model, oneOfInterfaceNames)) {
model.getVendorExtensions().put("x-jaxrs-record", true);
// Records have no field initializers: defaults (and the JsonNullable undefined
// state) must be applied in a compact canonical constructor.
if (model.vars.stream().anyMatch(v -> v.defaultValue != null
|| Boolean.TRUE.equals(v.getVendorExtensions().get("x-is-jackson-optional-nullable")))) {
model.getVendorExtensions().put("x-jaxrs-record-has-defaults", true);
}
// The implicit record equals/hashCode compares arrays by reference; mirror the
// pojo's Arrays.equals/hashCode semantics for byte[] properties.
if (model.vars.stream().anyMatch(v -> v.isByteArray)) {
model.getVendorExtensions().put("x-jaxrs-record-has-byte-array", true);
}
// The implicit record toString prints component values; mask password properties
// like the pojo does.
if (model.vars.stream().anyMatch(v -> v.isPassword)) {
model.getVendorExtensions().put("x-jaxrs-record-has-password", true);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<helidon.version>{{helidonVersion}}</helidon.version>
<mainClass>io.helidon.microprofile.cdi.Main</mainClass>

<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.source>{{#useSealed}}17{{/useSealed}}{{^useSealed}}{{#useRecords}}17{{/useRecords}}{{^useRecords}}11{{/useRecords}}{{/useSealed}}</maven.compiler.source>
<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
<maven.site.skip>true</maven.site.skip>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
<description>The microservice was generated automatically with the OpenAPI Generator project</description>

<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>{{#useSealed}}17{{/useSealed}}{{^useSealed}}{{#useRecords}}17{{/useRecords}}{{^useRecords}}1.8{{/useRecords}}{{/useSealed}}</maven.compiler.source>
<maven.compiler.target>{{#useSealed}}17{{/useSealed}}{{^useSealed}}{{#useRecords}}17{{/useRecords}}{{^useRecords}}1.8{{/useRecords}}{{/useSealed}}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<kumuluzee.version>3.9.0</kumuluzee.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>{{#useSealed}}17{{/useSealed}}{{^useSealed}}{{#useRecords}}17{{/useRecords}}{{^useRecords}}1.8{{/useRecords}}{{/useSealed}}</maven.compiler.source>
<maven.compiler.target>{{#useSealed}}17{{/useSealed}}{{^useSealed}}{{#useRecords}}17{{/useRecords}}{{^useRecords}}1.8{{/useRecords}}{{/useSealed}}</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
<version.maven-war-plugin>3.2.2</version.maven-war-plugin>
<!-- OpenLiberty runtime -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
<properties>
<compiler-plugin.version>3.8.1</compiler-plugin.version>
<maven.compiler.parameters>true</maven.compiler.parameters>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>{{#useSealed}}17{{/useSealed}}{{^useSealed}}{{#useRecords}}17{{/useRecords}}{{^useRecords}}1.8{{/useRecords}}{{/useSealed}}</maven.compiler.source>
<maven.compiler.target>{{#useSealed}}17{{/useSealed}}{{^useSealed}}{{#useRecords}}17{{/useRecords}}{{^useRecords}}1.8{{/useRecords}}{{/useSealed}}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
{{#useJakartaEe}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
<properties>
<version.thorntail>2.5.0.Final</version.thorntail>
<version.junit>5.14.4</version.junit>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>{{#useSealed}}17{{/useSealed}}{{^useSealed}}{{#useRecords}}17{{/useRecords}}{{^useRecords}}1.8{{/useRecords}}{{/useSealed}}</maven.compiler.source>
<maven.compiler.target>{{#useSealed}}17{{/useSealed}}{{^useSealed}}{{#useRecords}}17{{/useRecords}}{{^useRecords}}1.8{{/useRecords}}{{/useSealed}}</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,18 @@ import io.swagger.annotations.*;
{{#useSwaggerV3Annotations}}
import io.swagger.v3.oas.annotations.media.Schema;
{{/useSwaggerV3Annotations}}
{{#vendorExtensions.x-jaxrs-record-has-byte-array}}
import java.util.Objects;
{{/vendorExtensions.x-jaxrs-record-has-byte-array}}
{{#jackson}}
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.annotation.JsonTypeName;
{{/jackson}}
{{#withXml}}
import {{javaxPackage}}.xml.bind.annotation.XmlElement;
import {{javaxPackage}}.xml.bind.annotation.XmlRootElement;
import {{javaxPackage}}.xml.bind.annotation.XmlAccessType;
import {{javaxPackage}}.xml.bind.annotation.XmlAccessorType;
import {{javaxPackage}}.xml.bind.annotation.XmlType;
import {{javaxPackage}}.xml.bind.annotation.XmlEnum;
import {{javaxPackage}}.xml.bind.annotation.XmlEnumValue;
{{/withXml}}
{{! JsonNullable is already contributed through the imports block above for the models that use
it, so importing it here as well produced a duplicate import, and an unused one on records
with no nullable component - which broke libraries whose pom omits jackson-databind-nullable. }}

{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{#description}}/**
* {{.}}
Expand Down Expand Up @@ -46,7 +44,16 @@ public {{>sealed}}record {{classname}}(
{{#deprecated}}
@Deprecated
{{/deprecated}}
{{#jackson}}@JsonProperty({{#required}}required = {{required}}, value = {{/required}}"{{baseName}}") {{/jackson}}{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}}{{{datatypeWithEnum}}} {{name}}{{^-last}},{{/-last}}
{{#useSwaggerAnnotations}}
@ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
{{/useSwaggerAnnotations}}
{{#useSwaggerV3Annotations}}
@Schema({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}description = "{{{description}}}"{{#deprecated}}, deprecated = true{{/deprecated}})
{{/useSwaggerV3Annotations}}
{{#useMicroProfileOpenAPIAnnotations}}
@org.eclipse.microprofile.openapi.annotations.media.Schema({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}description = "{{{description}}}"{{#deprecated}}, deprecated = true{{/deprecated}})
{{/useMicroProfileOpenAPIAnnotations}}
{{#jackson}}@JsonProperty({{#required}}required = {{required}}, value = {{/required}}"{{baseName}}") {{/jackson}}{{#vendorExtensions.x-is-jackson-optional-nullable}}JsonNullable<{{{datatypeWithEnum}}}>{{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}}{{{datatypeWithEnum}}}{{/vendorExtensions.x-is-jackson-optional-nullable}} {{name}}{{^-last}},{{/-last}}
{{/vars}}
) {{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-implements}} {
{{#vars}}
Expand All @@ -61,4 +68,93 @@ public {{>sealed}}record {{classname}}(
{{/isContainer}}
{{/isEnum}}
{{/vars}}
{{#vendorExtensions.x-jaxrs-record-has-defaults}}
public {{classname}} {
{{#vars}}
{{#vendorExtensions.x-is-jackson-optional-nullable}}
if ({{name}} == null) {
{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#isContainer}}undefined(){{/isContainer}}{{^isContainer}}{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}{{/isContainer}};
}
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
{{#defaultValue}}
if ({{name}} == null) {
{{name}} = {{{.}}};
}
{{/defaultValue}}
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{/vars}}
}

{{/vendorExtensions.x-jaxrs-record-has-defaults}}
{{#vendorExtensions.x-jaxrs-record-has-byte-array}}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
{{classname}} {{classVarName}} = ({{classname}}) o;
return {{#vars}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{^-last}} &&
{{/-last}}{{/vars}};
}

@Override
public int hashCode() {
return Objects.hash({{#vars}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{^-last}}, {{/-last}}{{/vars}});
}

{{/vendorExtensions.x-jaxrs-record-has-byte-array}}
{{#vendorExtensions.x-jaxrs-record-has-password}}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class {{classname}} {\n");
{{#vars}}sb.append(" {{name}}: ").append({{#isPassword}}"*"{{/isPassword}}{{^isPassword}}toIndentedString({{name}}){{/isPassword}}).append("\n");
{{/vars}}sb.append("}");
return sb.toString();
}

/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(Object o) {
return o == null ? "null" : o.toString().replace("\n", "\n ");
}

{{/vendorExtensions.x-jaxrs-record-has-password}}
{{#generateBuilders}}
public static {{classname}}Builder builder() {
return new {{classname}}Builder();
}

public static class {{classname}}Builder {
{{#vars}}
{{#vendorExtensions.x-is-jackson-optional-nullable}}
private JsonNullable<{{#removeAnnotations}}{{{datatypeWithEnum}}}{{/removeAnnotations}}> {{name}} = JsonNullable.<{{#removeAnnotations}}{{{datatypeWithEnum}}}{{/removeAnnotations}}>{{#isContainer}}undefined(){{/isContainer}}{{^isContainer}}{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}{{/isContainer}};
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
private {{#removeAnnotations}}{{{datatypeWithEnum}}}{{/removeAnnotations}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{/vars}}

{{#vars}}
{{#deprecated}}
@Deprecated
{{/deprecated}}
public {{classname}}Builder {{name}}({{#removeAnnotations}}{{{datatypeWithEnum}}}{{/removeAnnotations}} {{name}}) {
this.{{name}} = {{#vendorExtensions.x-is-jackson-optional-nullable}}JsonNullable.<{{#removeAnnotations}}{{{datatypeWithEnum}}}{{/removeAnnotations}}>of({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{name}}{{/vendorExtensions.x-is-jackson-optional-nullable}};
return this;
}
{{/vars}}

public {{classname}} build() {
return new {{classname}}({{#vars}}{{name}}{{^-last}}, {{/-last}}{{/vars}});
}
}

{{/generateBuilders}}
}
Loading
Loading