jooby-project / jooby

The modular web framework for Java and Kotlin
https://jooby.io
Apache License 2.0
1.7k stars 200 forks source link

openapi: unused path parameter produces an error #3483

Closed jonaskahn closed 1 month ago

jonaskahn commented 1 month ago

I created project from jooby command cli with openapi. From the beginning, it worked pretty well, after I made some change. I can't generate OPEN API , it always throw error Failed to execute goal io.jooby:jooby-maven-plugin:3.2.6:openapi (default) on project api: execution of openapi resulted in exception: Kotlin lambda not found: io/jooby/kt/Kooby.<init>(Lkotlin/jvm/functions/Function1;)V -> [Help 1]

Could you point me out which's wrong? Here is my pom setting

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

    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>io.github.jonaskahn</groupId>
        <artifactId>parent</artifactId>
        <version>1.0.0</version>
    </parent>

    <artifactId>api</artifactId>
    <name>ADMIN API</name>

    <properties>
        <application.class>io.github.jonaskahn.AppKt</application.class>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>${hibernate-validator.version}</version>
        </dependency>
        <dependency>
            <groupId>jakarta.el</groupId>
            <artifactId>jakarta.el-api</artifactId>
            <version>${jakarta.el.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.expressly</groupId>
            <artifactId>expressly</artifactId>
            <version>${expressly.version}</version>
        </dependency>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>${redis.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${mapstruct.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>${commons-lang3.version}</version>
        </dependency>

        <dependency>
            <groupId>io.hypersistence</groupId>
            <artifactId>hypersistence-tsid</artifactId>
            <version>${tsid.version}</version>
        </dependency>

        <dependency>
            <groupId>at.favre.lib</groupId>
            <artifactId>bcrypt</artifactId>
            <version>${bcrypt-version}</version>
        </dependency>

        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk8</artifactId>
            <version>${kotlin.version}</version>
        </dependency>

        <dependency>
            <groupId>io.jooby</groupId>
            <artifactId>jooby-kotlin</artifactId>
        </dependency>

        <dependency>
            <groupId>io.jooby</groupId>
            <artifactId>jooby-guice</artifactId>
        </dependency>

        <!--DATABASE-->
        <dependency>
            <groupId>io.jooby</groupId>
            <artifactId>jooby-hikari</artifactId>
        </dependency>
        <dependency>
            <groupId>io.jooby</groupId>
            <artifactId>jooby-hibernate</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mariadb.jdbc</groupId>
            <artifactId>mariadb-java-client</artifactId>
            <version>${mariadb.version}</version>
        </dependency>

        <dependency>
            <groupId>io.jooby</groupId>
            <artifactId>jooby-flyway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-mysql</artifactId>
            <version>${flyway.version}</version>
        </dependency>

        <dependency>
            <groupId>io.jooby</groupId>
            <artifactId>jooby-jackson</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
            <version>${jackson-datatype-jsr310.version}</version>
        </dependency>

        <dependency>
            <groupId>io.swagger.core.v3</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>${swagger.version}</version>
        </dependency>
        <dependency>
            <groupId>io.jooby</groupId>
            <artifactId>jooby-swagger-ui</artifactId>
        </dependency>
        <dependency>
            <groupId>io.jooby</groupId>
            <artifactId>jooby-netty</artifactId>
        </dependency>

        <dependency>
            <groupId>io.jooby</groupId>
            <artifactId>jooby-logback</artifactId>
        </dependency>

        <dependency>
            <groupId>io.jooby</groupId>
            <artifactId>jooby-pac4j</artifactId>
        </dependency>

        <dependency>
            <groupId>org.pac4j</groupId>
            <artifactId>pac4j-jwt</artifactId>
        </dependency>

        <!-- Tests -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.10.2</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.10.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.jooby</groupId>
            <artifactId>jooby-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.12.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-test</artifactId>
            <version>${kotlin.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <sourceDirectory>${project.basedir}${file.separator}src${file.separator}main${file.separator}kotlin</sourceDirectory>
        <testSourceDirectory>${project.basedir}${file.separator}src${file.separator}test${file.separator}kotlin</testSourceDirectory>
        <resources>
            <resource>
                <directory>conf</directory>
            </resource>
            <resource>
                <directory>src${file.separator}main${file.separator}resources</directory>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <version>${kotlin.version}</version>
                <configuration>
                    <args>
                        <arg>-java-parameters</arg>
                    </args>
                    <jvmTarget>${maven.compiler.target}</jvmTarget>
                </configuration>
                <executions>
                    <execution>
                        <id>kapt</id>
                        <goals>
                            <goal>kapt</goal>
                        </goals>
                        <configuration>
                            <sourceDirs>
                                <sourceDir>src/main/kotlin</sourceDir>
                            </sourceDirs>
                            <annotationProcessorPaths>
                                <annotationProcessorPath>
                                    <groupId>org.mapstruct</groupId>
                                    <artifactId>mapstruct-processor</artifactId>
                                    <version>${mapstruct.version}</version>
                                </annotationProcessorPath>
                                <annotationProcessorPath>
                                    <groupId>io.jooby</groupId>
                                    <artifactId>jooby-apt</artifactId>
                                    <version>${jooby.version}</version>
                                </annotationProcessorPath>
                            </annotationProcessorPaths>
                            <annotationProcessorArgs>
                                <annotationProcessorArg>
                                    jooby.debug=false
                                </annotationProcessorArg>
                                <annotationProcessorArg>
                                    jooby.services=true
                                </annotationProcessorArg>
                            </annotationProcessorArgs>
                        </configuration>
                    </execution>
                    <execution>
                        <id>compile</id>
                        <phase>process-sources</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <goals>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.3.1</version>
            </plugin>
            <!-- jooby:run -->
            <plugin>
                <groupId>io.jooby</groupId>
                <artifactId>jooby-maven-plugin</artifactId>
                <version>${jooby.version}</version>
                <executions>
                    <execution>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>openapi</goal>
                        </goals>
                        <configuration>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-reflect</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
            <!-- Build uber jar -->
            <plugin>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.6.0</version>
                <executions>
                    <execution>
                        <id>uber-jar</id>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <createDependencyReducedPom>false</createDependencyReducedPom>
                            <transformers>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>${application.class}</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.jooby</groupId>
                <artifactId>jooby-bom</artifactId>
                <version>${jooby.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

UPDATE 1

I guess I found the reason why. So I used anonymous object to group routes like

fun Kooby.routes() {
    mount("/api", object : Kooby({
        install(JacksonModule(JsonMapper.instance))
        mvc(HealthController::class.java)
        mvc(AuthController::class.java)
        mvc(UserController::class.java)
        mvc(TestRoleController::class.java)
    }) {})
}
class App : Kooby({
...
    routes()
...
})

I change to declare a specific class like

fun Kooby.routes() {
    mount("/api", Router())
}

private class Router : Kooby({
    install(JacksonModule(JsonMapper.instance))
    mvc(HealthController::class.java)
    mvc(AuthController::class.java)
    mvc(UserController::class.java)
    mvc(TestRoleController::class.java)
})

And now, it lead me to another error Caused by: java.lang.NullPointerException: Cannot invoke "java.util.List.stream()" because the return value of "io.jooby.internal.openapi.OperationExt.getParameters()" is null at io.jooby.internal.openapi.OperationExt.getParameter (OperationExt.java:138) at io.jooby.openapi.OpenAPIGenerator.generate (OpenAPIGenerator.java:211)

UPDATE 2

I found the reason for the error above, I guess we have some conflictions

I tried to used static files that built in vuejs. So, To tell vuejs handle menu link I delcare some routes like belove


fun Kooby.web() {

    assets("/*", "static")

    get("/uikit*") {
        ctx.forward("/")
    }
    get("/blocks*") {
        ctx.forward("/")
    }
    get("/utilities*") {
        ctx.forward("/")
    }
    get("/documentation*") {
        ctx.forward("/")
    }
}

These line break the maven build, if I remove get line. It works.

UPDATE 3. I come closer to the issue

jknack commented 1 month ago

Don't think the issue is on the *. We need to isolate the offending mapping/function

jonaskahn commented 1 month ago

I still think it's a bug. I do create a fresh start project This will lead program to an error when maven run


class App: Kooby({
  install(NettyServer())
  install(OpenAPIModule())
  mvc(Controller_())

  get("/api/*") {
    ctx.forward("/")
  }

})

fun main(args: Array<String>) {
  runApp(args, ::App)
}

If I change to get(/api/) , it will work.


class App: Kooby({
  install(NettyServer())
  install(OpenAPIModule())
  mvc(Controller_())

  get("/api/") {
    ctx.forward("/")
  }

})

fun main(args: Array<String>) {
  runApp(args, ::App)
}
jknack commented 1 month ago

with script/lambda routes the open api parser expect to find the parameter in source code, so:

  get("/some/*") {
     val value = ctx.path("*").value()
      ...
  }

Works, while this one won't:

  get("/some/*") {
      // never retrieve the *
      ctx.forward("/")
  }

That is the bug