Generate JAVA code from OpenAPI specification

Recently, I started a project and I chose Gradle as the build tool. In this project, I had to integrate with an external service that has an API documented in OpenAPI format. So, first of all, I had to import the OpenAPI Generator plugin into my project. Import Generator plugin plugins { id("java-library") id("org.openapi.generator") version "7.12.0" } Plugin configuration After importing the plugin, some configuration was needed. openApiGenerate { generatorName.set("spring") inputSpec.set("$projectDir/src/main/resources/openapi/center-api-v1.yaml") outputDir.set("${layout.buildDirectory.get()}/generated") validateSpec.set(true) modelPackage.set("com.example.my-project.model") generateModelDocumentation.set(false) configOptions.set( mapOf( "dateLibrary" to "java8", "useJakartaEE" to "true", "useRuntimeException" to "true", "useSpringBoot3" to "true", ) ) } I set the generator to spring. The generatorName setting controls what kind of code gets generated based on the OpenAPI spec — essentially, it determines the language and framework you're targeting. This setting influences the structure of the generated code, its dependencies, annotations and libraries it uses. With inputSpec I specified the absolute path of the OpenAPI configuration. outputDir property tells openapi-generator where to the generated code. I wanted to ensure the OpenAPI specification is valid, so I set validateSpec to true. With the modelPackage property, I specified where the tool should place the generated model classes. I didn't specify the apiPackage property, because I only needed the DTOs. Through the configOptions you can set many additional properties. Here's a breakdown of what I used: dateLibrary set to java8 tells the generator tool to use LocalDate and LocalDateTime to store temporal data. useJakartaEEset to true ensures the generated code uses the jakarta.* namespace instead of javax.*. useRuntimeException set to true instructs the generator to use unchecked exceptions in the generated code. useSpringBoot3 set to true is a essential because I used SpringBoot 3.x in this project. Spring Boot 3 dropped support for the old javax.* namespace in favor of jakarta.* (a change introduced with Jakarta EE 9+). Without this flag, the generated code might use outdated annotations and could fail to compile. Additionally, it adjusts dependencies and code structure to align with Spring Boot 3 requirements, making the generated code ready to use out of the box. Further tweaks I configured the compileJava task to automatically run the openApiGenerate task. This way, running the build task will generate appropriate JAVA from the OpenAPI specification every time. tasks.named("compileJava") { dependsOn(tasks.named("openApiGenerate")) } Last, but not least, I had to configure the source sets. Without this configuration, the generated code would be outside of the compiler's scope. The following code snippet adds the directory containing the generated code to put the project's sources. sourceSets { main { java { srcDir("${layout.buildDirectory.get()}/generated/src/main/java") } } } List sourceSets This snippet is just a helpful trick. If you're relatively new to Gralde - like I am - and want to check what's in the sourceSets after applying the above settings, you can use the following snippet: tasks.register("printSourceSetInfo", DefaultTask::class) { // Get the names and source directories at configuration time val sourceSetInfo = (project.extensions.getByName("sourceSets") as SourceSetContainer) .associate { sourceSet -> sourceSet.name to sourceSet.allSource.srcDirs.map(File::getAbsolutePath) } doLast { sourceSetInfo.forEach { (name, srcDirs) -> println("SourceSet: $name") srcDirs.forEach { dir -> println(" -> $dir") } } } } This registers a task named printSourceSetInfo, fetches information about the current sourceSets, and prints each set's name along with its associated source directories. Resources: OpenAPI Generator Gradle Plugin Documentation for the spring Generator

Apr 15, 2025 - 16:05
 0
Generate JAVA code from OpenAPI specification

Recently, I started a project and I chose Gradle as the build tool. In this project, I had to integrate with an external service that has an API documented in OpenAPI format. So, first of all, I had to import the OpenAPI Generator plugin into my project.

Import Generator plugin

plugins {
    id("java-library")
    id("org.openapi.generator") version "7.12.0"
}

Plugin configuration

After importing the plugin, some configuration was needed.

openApiGenerate {
    generatorName.set("spring")
    inputSpec.set("$projectDir/src/main/resources/openapi/center-api-v1.yaml")    
    outputDir.set("${layout.buildDirectory.get()}/generated")
    validateSpec.set(true)

    modelPackage.set("com.example.my-project.model")
    generateModelDocumentation.set(false)

    configOptions.set(
        mapOf(
            "dateLibrary" to "java8",
            "useJakartaEE" to "true",
            "useRuntimeException" to "true",
            "useSpringBoot3" to "true",
        )
    )
}
  • I set the generator to spring. The generatorName setting controls what kind of code gets generated based on the OpenAPI spec — essentially, it determines the language and framework you're targeting. This setting influences the structure of the generated code, its dependencies, annotations and libraries it uses.
  • With inputSpec I specified the absolute path of the OpenAPI configuration.
  • outputDir property tells openapi-generator where to the generated code.
  • I wanted to ensure the OpenAPI specification is valid, so I set validateSpec to true.
  • With the modelPackage property, I specified where the tool should place the generated model classes. I didn't specify the apiPackage property, because I only needed the DTOs.
  • Through the configOptions you can set many additional properties. Here's a breakdown of what I used:
    • dateLibrary set to java8 tells the generator tool to use LocalDate and LocalDateTime to store temporal data.
    • useJakartaEEset to true ensures the generated code uses the jakarta.* namespace instead of javax.*.
    • useRuntimeException set to true instructs the generator to use unchecked exceptions in the generated code.
    • useSpringBoot3 set to true is a essential because I used SpringBoot 3.x in this project. Spring Boot 3 dropped support for the old javax.* namespace in favor of jakarta.* (a change introduced with Jakarta EE 9+). Without this flag, the generated code might use outdated annotations and could fail to compile. Additionally, it adjusts dependencies and code structure to align with Spring Boot 3 requirements, making the generated code ready to use out of the box.

Further tweaks

I configured the compileJava task to automatically run the openApiGenerate task. This way, running the build task will generate appropriate JAVA from the OpenAPI specification every time.

tasks.named<JavaCompile>("compileJava") {
    dependsOn(tasks.named("openApiGenerate"))
}

Last, but not least, I had to configure the source sets. Without this configuration, the generated code would be outside of the compiler's scope. The following code snippet adds the directory containing the generated code to put the project's sources.

sourceSets {
    main {
        java {
            srcDir("${layout.buildDirectory.get()}/generated/src/main/java")
        }
    }
}

List sourceSets

This snippet is just a helpful trick. If you're relatively new to Gralde - like I am - and want to check what's in the sourceSets after applying the above settings, you can use the following snippet:

tasks.register("printSourceSetInfo", DefaultTask::class) {
    // Get the names and source directories at configuration time
    val sourceSetInfo = (project.extensions.getByName("sourceSets") as SourceSetContainer)
        .associate { sourceSet ->
            sourceSet.name to sourceSet.allSource.srcDirs.map(File::getAbsolutePath)
        }

    doLast {
        sourceSetInfo.forEach { (name, srcDirs) ->
            println("SourceSet: $name")
            srcDirs.forEach { dir ->
                println("  -> $dir")
            }
        }
    }
}

This registers a task named printSourceSetInfo, fetches information about the current sourceSets, and prints each set's name along with its associated source directories.

Resources: