Can I generate immutable models with open api generator without changing the mustache templates? My first thought was that the generator could be configured to generate Java records but I can't find any information on how to do this. I've also included the @Value lombok annotation in the generator config but setters are still generated due to the caveat that I have to modify the mustache templates to omit setters which is not currently an option.
I understand that it is not yet possible to use record with the OpenApi Generator, I want to do it too.
For my part the use of mustache I think it requires a learning curve, that few will want to live it.
But as an option what we are doing in our project is the use of OpenApi Generator Ignore
Is a file that you include for the generator to ignore the classes you want, plus a tag in the pom.xml to process this file.
The record as such, must be created by you, and include it in your Apis project if you have it separated from backend, also you must upload the src/main/java folder to your repository at least with the record, in my case it was necessary for nexus to build the artifact with the record inside, you can then decompile the .jar to test.
This record is for the typicode response https://jsonplaceholder.typicode.com/todos/2
This is not the perfect example but it can be useful, I have included the src/main/java just for having a record generated by me.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>7.2.0</version>
<ignoreFileOverride>${project.basedir}/src/main/resources/openapi-rest/.openapi-generator-ignore</ignoreFileOverride>
The @Jacksonized annotation in the record I am using it for testing purposes but if you want you can remove it, it is working for me with or without it.
@Builder
@Jacksonized
public record TestRecordResponse(
@Schema(name = "userId", example = "1", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
String userId,
@Schema(name = "id", example = "2", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
String id,
@Schema(name = "title", example = "quis ut nam facilis et officia qui", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
String title,
@Schema(name = "completed", example = "false|true", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
Boolean completed) {
}
The Schema annotation seems to be necessary for this case, when I write it in the openapi-rest.yml the documentation is not displayed in the swagger.
In other words, it is not enough to write this.
TestRecordResponse:
type: object
properties:
id:
type: string
example: "2"
userId:
type: string
example: "1"
title:
type: string
example: "quis ut nam facilis et officia qui"
completed:
type: boolean
example: true | false
the following image shows a better documented record now.

When you build your api with maven, in the logs you should be able to see something like this, which indicates that your record is intact.

import static org.assertj.core.api.Assertions.*;
class WebClientSimpleTypiCodeTest {
@SneakyThrows
@ParameterizedTest
@MethodSource("getTestRecord")
@DisplayName("A simple get to the endpoint of the free jsonplaceholder service typicode.com")
void simpleGet(final TestRecordResponse expectedTestRecordResponse) {
final CountDownLatch latch = new CountDownLatch(1);
WebClient.create("https://jsonplaceholder.typicode.com")
.get()
.uri("/todos/2")
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(TestRecordResponse.class)
.log()
.doOnTerminate(latch::countDown)
.subscribe(actualTestRecordResponse -> {
assertThat(actualTestRecordResponse)
.isNotNull()
.usingRecursiveComparison()
.isEqualTo(expectedTestRecordResponse);
});
latch.await();
}
private static Stream<TestRecordResponse> getTestRecord() {
final TestRecordResponse expectedTestRecordResponse = TestRecordResponse.builder()
.id("2")
.userId("1")
.title("quis ut nam facilis et officia qui")
.completed(false)
.build();
return Stream.of(expectedTestRecordResponse);
}
}

This was the response with the image-1 of the deployed source https://github.com/rucko24/gitlab-test
curl -X 'GET' 'http://localhost:8082/api/v1/test-record' -H 'accept: application/json'

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With