Description
java-micronaut-server And generateControllerAsAbstract=true Results in "class not found" Errors
I opted to not create a [BUG] issue, since the java-micronaut-server is still listed as a Beta version.
While working on a short article that leverages and OpenAPI specification to build services, I was able to successfully use Spring Boot and Quarkus. The final article of my series focused on Micronaut and I was excited to see that an OpenAPI generator exists for this framework.
By default, the 7.12.0 version of the generator ends up creating a DefaultController
which is a class. I eventually discovered the generateControllerAsAbstract=true
configuration option which did introduce the AbstractDefaultController
however, with this change in place I started seeing "class not found" errors. What surprised me is that errors pointed to HttpStatusException
and HttpStatus
- both of which were in the class path and available in my local IntelliJ instance. If I were to switch back to generateControllerAsAbstract=false
, the errors went away.
I also noticed that if I provided my own api, model and invoker packages, the AbstractDefaultController
appeared to ignore these settings and created the class in the org.openapitools
package.
Here is my build.gradle
file:
plugins { id("io.micronaut.application") version "4.5.0" id("com.gradleup.shadow") version "8.3.6" id("io.micronaut.aot") version "4.5.0" id("org.openapi.generator") version '7.12.0' } openApiGenerate { generatorName = "java-micronaut-server" inputSpec = "$rootDir/src/main/resources/openapi.yaml" outputDir = "$buildDir/generated" //apiPackage = "quotes.micronaut.openapi.api" //modelPackage = "quotes.micronaut.openapi.model" //invokerPackage = "quotes.micronaut.openapi.invoker" configOptions = [ dateLibrary: "java8", useJakartaEe: "true", useBeanValidation: "false", reactive: "false", generateControllerAsAbstract: "true", ] } version = "0.1" group = "quotes.micronaut" repositories { mavenCentral() } dependencies { annotationProcessor("io.micronaut:micronaut-http-validation") annotationProcessor("io.micronaut:micronaut-inject-java") annotationProcessor("io.micronaut.openapi:micronaut-openapi") annotationProcessor("io.micronaut.serde:micronaut-serde-processor") annotationProcessor("io.micronaut.validation:micronaut-validation-processor") annotationProcessor("org.projectlombok:lombok") implementation("io.micronaut:micronaut-http") implementation("io.micronaut.security:micronaut-security-annotations") implementation("io.micronaut.security:micronaut-security") implementation("io.micronaut.serde:micronaut-serde-jackson") implementation("io.micronaut.validation:micronaut-validation") compileOnly("io.micronaut:micronaut-http-server") compileOnly("io.micronaut.openapi:micronaut-openapi-annotations") compileOnly("org.projectlombok:lombok") runtimeOnly("ch.qos.logback:logback-classic") testImplementation("io.micronaut:micronaut-http-client") } application { mainClass = "quotes.micronaut.Application" } java { sourceCompatibility = JavaVersion.toVersion("17") targetCompatibility = JavaVersion.toVersion("17") } sourceSets { main { java { srcDirs += "$buildDir/generated/src/main/java" } } } compileJava.dependsOn tasks.openApiGenerate graalvmNative.toolchainDetection = false micronaut { runtime("netty") testRuntime("junit5") processing { incremental(true) annotations("quotes.micronaut.*") } aot { // Please review carefully the optimizations enabled below // Check https://micronaut-projects.github.io/micronaut-aot/latest/guide/ for more details optimizeServiceLoading = false convertYamlToJava = false precomputeOperations = true cacheEnvironment = true optimizeClassLoading = true deduceEnvironment = true optimizeNetty = true replaceLogbackXml = true } }
If interested, here's the OpenAPI Specification that I have been using for my articles:
openapi: 3.0.0 info: title: Motivational Quotes API description: An API that provides motivational quotes. version: 1.0.0 servers: - url: https://api.example.com description: Production server paths: /quotes: get: summary: Get all motivational quotes operationId: getAllQuotes responses: '200': description: A list of motivational quotes content: application/json: schema: type: array items: $ref: '#/components/schemas/Quote' /quotes/random: get: summary: Get a random motivational quote operationId: getRandomQuote responses: '200': description: A random motivational quote content: application/json: schema: $ref: '#/components/schemas/Quote' /quotes/{id}: get: summary: Get a motivational quote by ID operationId: getQuoteById parameters: - name: id in: path required: true schema: type: integer responses: '200': description: A motivational quote content: application/json: schema: $ref: '#/components/schemas/Quote' '404': description: Quote not found components: schemas: Quote: type: object required: - id - quote properties: id: type: integer quote: type: string
I opted to go a different direction for the article, but I wanted to log this ticket, in case it provides value for someone else in the future.
Have a really great day!