code(kotlin):
@Validated
@RestController
@RequestMapping("/admin/system/sysRole")
class SysRoleController(
private val sysRoleService: SysRoleService
) {
/**
* Get page list.
*/
@GetMapping("/{page}/{limit}")
fun index(
@PathVariable page: Int,
@PathVariable limit: Int,
@Nullable roleQueryVo: SysRoleQueryVo?
): Result<*> {
val pageParam: Pageable = if (page == 0) PageRequest.of(page, limit) else PageRequest.of(page - 1, limit)
val pageModel: Page<SysRole> = sysRoleService.selectPage(pageParam, roleQueryVo)
return Result.ok(pageModel)
}
}
error message:
java.lang.IllegalStateException: No primary or single unique constructor found for class xx.xx.xx.SysRoleQueryVo
at org.springframework.beans.BeanUtils.getResolvableConstructor(BeanUtils.java:266)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:219)
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:85)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:147)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:181)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:148)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1080)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:973)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1010)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:902)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:705)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:884)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:223)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:859)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1734)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base@17.0.5/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)
I tried to call the HTTP interface in the JVM without passing the VO object, which is perfect. However, this exception occurs when the HTTP interface is called in the same way after the native compilation.
maven:
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<artifactId>demo</artifactId>
<groupId>xx.xx</groupId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<classifier>jakarta</classifier>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<scope>provided</scope>
<classifier>jakarta</classifier>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<mainClass>xx.xx.xx.DemoApplicationKt</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>spring</plugin>
<plugin>jpa</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-noarg</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
system : windows 11 jdk: openjdk version "17.0.5" 2022-10-18 LTS GraalVM 22.3.0 maven: 3.8.1
Comment From: wilkinsona
It looks like there's some reflection metadata missing that prevents the constructors of xx.xx.xx.SysRoleQueryVo
from being found. Such metadata should be generated automatically by Spring Framework due to its use as an argument of a @GetMapping
method. We'll transfer this to the Framework team so that they can investigate.
Comment From: sdeleuze
A known limitation of ControllerMappingReflectiveProcessor
is that it only registers reflection hint for parameters annotated with @RequestBody
, @ModelAttribute
and @RequestPart
, I have refined the Javadoc as part of #29938 accordingly. So if you are relying on the ModelAttributeMethodProcessor
initialized with annotationNotRequired=true
to have implicit handling of the SysRoleQueryVo
parameter, the reflection hint inference won't be performed on native because the "signal" is too complex to infer.
Before discussing what we should do, could you please confirm this is your use case, and that it works with @ModelAttribute
?
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: OrdinarySF
yes, this is my user case. I tried to use @RequestParam(required=false)
, but it didn't work.
In fact, my requirement is only to return null values when there is no need to pass VO classes. However, the code that can run under the JVM environment cannot run under the native platform.
Comment From: sdeleuze
Could you please let me know if it works with @ModelAttribute roleQueryVo: SysRoleQueryVo?
?
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: OrdinarySF
It seems that adding @ModelAttribute
has a certain effect, but I still need to go through more tests!
Comment From: sdeleuze
@Holmes-shuai Could you please provide a refined feedback?
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: spring-projects-issues
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.
Comment From: holmofy
Has this problem been resolved. I also encountered this problem today.
Comment From: snicoll
@holmofy as you can see by yourself in the history of this issue, we were asking for more feedback and didn't get any. If you think you've a similar problem, please attach a small sample that reproduces the issue. You can do that by attaching a zip to this issue or by sharing a link to a GitHub repository.