javalin / javalin-openapi

Annotation processor for compile-time OpenAPI & JsonSchema, with out-of-the-box support for Javalin 5.x, Swagger & ReDoc
https://github.com/javalin/javalin-openapi/wiki
Apache License 2.0
45 stars 17 forks source link

Encountering "no api definition provided" Error with Javalin OpenAPI Annotations #215

Closed eris324 closed 4 months ago

eris324 commented 6 months ago

Hello I'm trying to document my REST API using OpenAPI annotations. Despite annotating my controller method with @OpenApi, I'm encountering a "no api definition provided" error when trying to access the generated documentation via Swagger UI or ReDoc.

Here's the relevant portion of my Kotlin code where I set up Javalin, configure the OpenAPI plugin, and define a simple UserController that I took from an example

package org.example

import io.javalin.Javalin
import io.javalin.apibuilder.ApiBuilder.*
import io.javalin.http.Context
import io.javalin.openapi.*
import io.javalin.openapi.plugin.OpenApiPlugin
import io.javalin.openapi.plugin.redoc.ReDocPlugin
import io.javalin.openapi.plugin.swagger.SwaggerPlugin
import java.util.concurrent.atomic.AtomicInteger

data class User(
    val id: Int,
    val name: String,
    val email: String
)

object UserService {

    private val users = hashMapOf(
        0 to User(id = 0, name = "Alice", email = "alice@alice.kt"),
        1 to User(id = 1, name = "Bob", email = "bob@bob.kt"),
        2 to User(id = 2, name = "Carol", email = "carol@carol.kt"),
        3 to User(id = 3, name = "Dave", email = "dave@dave.kt")
    )

    private var lastId: AtomicInteger = AtomicInteger(users.size - 1)

    fun getAll() = users.values
}

fun getConfiguredOpenApiPlugin(): OpenApiPlugin {
    return OpenApiPlugin { pluginConfig ->
        pluginConfig.withDefinitionConfiguration { _, definition ->
            definition.withInfo { info: OpenApiInfo ->
                info.title = "sentinel"
                info.version = "1.0.0"
                info.description = "sentinel"
            }
        }
        pluginConfig.documentationPath = "/swagger-docs"
    }
}

object UserController {
    @OpenApi(
        summary = "Get all users",
        operationId = "getAllUsers",
        tags = ["User"],
        responses = [OpenApiResponse("200", [OpenApiContent(Array<User>::class)])],
        path = "/users",
        methods = [HttpMethod.GET]
    )
    fun getAll(ctx: Context) {
        ctx.json(UserService.getAll())
    }
}
fun main() {

    Javalin.create { config ->
        config.registerPlugin(OpenApiPlugin { pluginConfig ->
            pluginConfig.withDefinitionConfiguration { version, definition ->
                definition.withInfo { info: OpenApiInfo ->
                    info.title = "Javalin OpenAPI example"
                }
            }
        })
        config.registerPlugin(SwaggerPlugin())
        config.registerPlugin(ReDocPlugin())
        config.router.apiBuilder {
            path("users") {
                get(UserController::getAll);
            }
        }
    }.start(7001)

    println("Check out ReDoc docs at http://localhost:7001/redoc")
    println("Check out Swagger UI docs at http://localhost:7001/swagger")

}

and the pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>untitled</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>11</java.version>
        <kotlin.version>1.9.22</kotlin.version>
        <kotlin.code.style>official</kotlin.code.style>
        <javalin.version>6.1.0</javalin.version>
    </properties>

    <dependencies>
        <!-- Kotlin -->
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-common</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-test</artifactId>
            <version>${kotlin.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- Javalin -->
        <dependency>
            <groupId>io.javalin</groupId>
            <artifactId>javalin-bundle</artifactId>
            <version>${javalin.version}</version>
        </dependency>

        <dependency>
            <groupId>io.javalin.community.openapi</groupId>
            <artifactId>javalin-openapi-plugin</artifactId>
            <version>${javalin.version}</version>
        </dependency>
        <dependency>
            <groupId>io.javalin.community.openapi</groupId>
            <artifactId>javalin-swagger-plugin</artifactId>
            <version>${javalin.version}</version>
        </dependency>
        <dependency>
            <groupId>io.javalin.community.openapi</groupId>
            <artifactId>javalin-redoc-plugin</artifactId>
            <version>${javalin.version}</version>
        </dependency>

    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <version>${kotlin.version}</version>
                <configuration>
                    <jvmTarget>11</jvmTarget>
                </configuration>
                <executions>
                    <execution>
                        <id>compile</id>
                        <phase>process-sources</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.10.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                    <annotationProcessorPaths>
                        <annotationProcessorPath>
                            <groupId>io.javalin.community.openapi</groupId>
                            <artifactId>openapi-annotation-processor</artifactId>
                            <version>6.0.0-SNAPSHOT</version>
                        </annotationProcessorPath>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.openapitools</groupId>
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <version>5.1.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <generatorName>kotlin</generatorName>
                            <inputSpec>${project.basedir}/src/main/resources/openapi.json</inputSpec>
                            <configOptions>
                                <sourceFolder>src/gen/java/main</sourceFolder>
                            </configOptions>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

But it seems not detected my definition

image

dzikoysk commented 6 months ago

Hey, you're using Kotlin with Java's annotation processor and that's why you don't get any results. You should use kapt, as far as I see it is supported Maven: