quarkiverse / quarkus-mybatis

Quarkus MyBatis Extension
Apache License 2.0
89 stars 33 forks source link

native build application do not work. #327

Closed OrdinarySF closed 1 year ago

OrdinarySF commented 1 year ago

env:

    <compiler-plugin.version>3.11.0</compiler-plugin.version>
    <kotlin.version>1.8.21</kotlin.version>
    <maven.compiler.release>17</maven.compiler.release>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
    <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
    <quarkus.platform.version>3.1.1.Final</quarkus.platform.version>
    <skipITs>true</skipITs>
    <surefire-plugin.version>3.0.0</surefire-plugin.version>

jdk: bellsoft-liberica-vm-openjdk17-22.3.1
quarkus-mybatis version : 2.0.0

demo code:

package com.example

import jakarta.enterprise.context.ApplicationScoped
import jakarta.inject.Inject
import jakarta.ws.rs.*
import jakarta.ws.rs.core.MediaType
import org.apache.ibatis.annotations.Mapper
import org.apache.ibatis.annotations.Select

@Path("/hello")
class ExampleResource {

    @Inject
    private lateinit var greetingService: GreetingService

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    fun hello(@QueryParam("age") age: Int, @QueryParam("name") name: String) =
        "Hello from RESTEasy Reactive, ${greetingService.greeting(name)}, age=$age"

    @GET
    @Path("user/{name}")
    @Produces(MediaType.APPLICATION_JSON)
    fun hello1(@PathParam(value = "name") name: String) = UserName(name)
}

@ApplicationScoped
class GreetingService {

    @Inject
    private lateinit var userMapper: UserMapper

    public fun greeting(name: String): String {
        val user: User? = userMapper.getByUsername(name)
//        val user1: User? = userMapper.selectOne(LambdaQueryWrapper(User::class.java).eq(User::getUsername, name))
//        println(user?.equals(user1))
        return "hello ${user?.username}!";
    }
}

data class UserName(val name: String)

@Mapper
interface UserMapper
//    : BaseMapper<User>
{

    @Select("select * from user where username = #{username}")
    fun getByUsername(username: String): User?
}

user.java

package com.example;

/**
 * @author Ordinary
 */
public class User {

    private String username;
    private String password;

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public User() {
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

native build command: mvn package -Pnative

error message:

__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2023-06-13 13:22:18,818 INFO  [io.quarkus] (main) quarkus_demo 1.0-SNAPSHOT native (powered by Quarkus 3.1.1.Final) started in 0.064s. Listening on: http://0.0.0.0:8080
2023-06-13 13:22:18,819 INFO  [io.quarkus] (main) Profile prod activated.
2023-06-13 13:22:18,819 INFO  [io.quarkus] (main) Installed features: [agroal, cdi, jdbc-mysql, kotlin, mybatis, narayana-jta, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, vertx]
2023-06-13 13:22:21,054 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-1) HTTP Request to /hello?name=sa&age=14 failed, error id: 58bec552-a11d-40f2-af7c-4bbcbf5c1ad4-1: org.apache.ibatis.exceptions.PersistenceException:
### Error querying database.  Cause: org.apache.ibatis.executor.ExecutorException: No constructor found in com.example.User matching [java.lang.String, java.lang.String]
### The error may exist in com/example/UserMapper.java (best guess)
### The error may involve com.example.UserMapper.getByUsername
### The error occurred while handling results
### SQL: select * from user where username = ?
### Cause: org.apache.ibatis.executor.ExecutorException: No constructor found in com.example.User matching [java.lang.String, java.lang.String]
        at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:153)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:145)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:76)
        at java.base@17.0.6/java.lang.reflect.Method.invoke(Method.java:568)
        at io.quarkiverse.mybatis.runtime.TransactionalSqlSession$TransactionalSqlSessionInterceptor.invoke(TransactionalSqlSession.java:197)
        at jdk.proxy4/jdk.proxy4.$Proxy98.selectOne(Unknown Source)
        at io.quarkiverse.mybatis.runtime.TransactionalSqlSession.selectOne(TransactionalSqlSession.java:46)
        at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:87)
        at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:145)
        at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86)
        at jdk.proxy4/jdk.proxy4.$Proxy59.getByUsername(Unknown Source)
        at com.example.GreetingService.greeting(ExampleResource.kt:34)
        at com.example.GreetingService_ClientProxy.greeting(Unknown Source)
        at com.example.ExampleResource.hello(ExampleResource.kt:19)
        at com.example.ExampleResource$quarkusrestinvoker$hello_8bc9220e302146786546fce1242234135cc56158.invoke(Unknown Source)
        at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
        at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
        at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
        at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
        at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
        at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base@17.0.6/java.lang.Thread.run(Thread.java:833)
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:775)
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.windows.WindowsPlatformThreads.osThreadStartRoutine(WindowsPlatformThreads.java:178)
Caused by: org.apache.ibatis.executor.ExecutorException: No constructor found in com.example.User matching [java.lang.String, java.lang.String]
        at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.lambda$createByConstructorSignature$1(DefaultResultSetHandler.java:705)
        at java.base@17.0.6/java.util.Optional.orElseThrow(Optional.java:403)
        at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createByConstructorSignature(DefaultResultSetHandler.java:704)
        at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(DefaultResultSetHandler.java:669)
        at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(DefaultResultSetHandler.java:642)
        at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getRowValue(DefaultResultSetHandler.java:404)
        at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValuesForSimpleResultMap(DefaultResultSetHandler.java:361)
        at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValues(DefaultResultSetHandler.java:335)
        at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSet(DefaultResultSetHandler.java:308)
        at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:201)
        at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:65)
        at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79)
        at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63)
        at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:325)
        at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
        at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109)
        at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:89)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:151)
        ... 27 more
zhfeng commented 1 year ago

Hi @Holmes-shuai ,

It seems like a similar issue with

Can you check to add @RegisterForReflection?

Also it seems that you are using kotlin?

OrdinarySF commented 1 year ago

yes , i using kotlin in the demo project.

I will try using this annotation.

OrdinarySF commented 1 year ago

I added @RegisterForReflection to the class (User), and it started working properly after the native compiler.

Thank you very much.

Furthermore, I found on the website various tips about the additional usages of this annotation and its native applications.

OrdinarySF commented 1 year ago

Based on multiple tests, I believe this issue has been resolved, so I will to close it.

zhfeng commented 1 year ago

Thanks @Holmes-shuai for sharing the solution. And I'd like to mention that we also have a Chinese localization website https://cn.quarkus.io/guides/writing-native-applications-tips

Out of curious, are you interesting to contribute for the quarkus guides translations? you can get more detail from https://github.com/quarkusio/cn.quarkus.io

OrdinarySF commented 1 year ago

Thank you for @zhfeng 's invitation. I will try to translate the documentation in my spare time.