Default Constructor Generation in Payload Classes - Spring Boot
I have integrated the sngular/scs-multiapi-plugin Gradle plugin into my Spring Boot application to generate POJOs for AVRO schemas to be used with Pulsar. However, I encountered an issue where the generated domain objects lack a default constructor, leading to internal exceptions when using Jackson to deserialize the objects in the Pulsar listener.
I believe the plugin could be enhanced or maybe even has a posibility in one of two ways to address this issue:
- Include an option to generate a default constructor for payload classes.
- Provide support for the builder pattern when generated payload classes are used in Spring Boot.
Adding either of these features would greatly improve the compatibility of the plugin with Spring Boot Pulsar Starter.
I kindly request the addition of this feature to the plugin to improve its usability in various environments. Thank you for your consideration.
Thank you for collaborating with the project by giving us feedback! Cheers!
The sngular/scs-multiapi-plugin Gradle plugin vesion used is id 'com.sngular.scs-multiapi-gradle-plugin' version '5.3.5'
Hi @malon875875, @WZHMIJJ,
That is odd because we are using the pattern builder in our generated POJOS, also if you are using Lombok @Builder annotation is added.
Can we get an example of the API you are trying to build?
Cheers
Yes, the builder is truly added, but the problem arrises that inside of Spring it does not instantiate the object. The problem is because of the domain object missing a default constructor and thus Jackson throws an internal exception.
Problem
- When creating Java classes with the AsyncAPI Generator, no empty Constructor is created. Spring does not instatiate the object.
Solution
- implement a workaround using lombok in build.gradle
- (sidenote: asyncapimodel.specFile has modelNameSuffix = 'DTO' )
// workaround to add lombok @NoArgsConstructor annotation to generated Java classes
task insertLombokAnnotation {
doLast {
fileTree('build/generated-source/').visit { FileVisitDetails details ->
if (details.file.name.endsWith('DTO.java')) {
def fileContents = details.file.text
def lines = fileContents.tokenize('\n')
def classLineIndex = lines.findIndexOf { it.trim().startsWith('public class') }
if (classLineIndex != -1) {
lines = lines[0..classLineIndex - 1] + "@NoArgsConstructor" + '\n' + lines[classLineIndex..-1]
details.file.text = lines.join('\n')
}
}
}
}
doLast {
fileTree('build/generated-source/').visit { FileVisitDetails details ->
if (details.file.name.endsWith('DTO.java')) {
def fileContents = details.file.text
def lines = fileContents.tokenize('\n')
lines = lines[0] + "\nimport lombok.NoArgsConstructor;" + '\n' + lines[1..-1].join('\n')
details.file.text = lines
}
}
}
}
tasks.withType(JavaCompile) {
dependsOn insertLombokAnnotation
}
// end workaround
Future Reference @jemacineiras It would be nice having a useLombokModelAnnotation for AsyncAPI Generator in the same way that it exists for the OpenAPI Generator