`@Resource` dependency injection fails with AOT/native
javamichi18 opened this issue · 8 comments
Affects: Spring 6.0.2 / SpringBoot 3.0.0 / GraalVM CE 22.3.0 (build 17.0.5+8-jvmci-22.3-b08)
Injection of spring beans fails when using @Resource
and native image.
When using @Autowired
the dependency injections works as expected.
example project:
https://github.com/javamichi18/graalDependencyTest
e.g.
@Controller
public class API {
@jakarta.annotation.Resource //--> NPE
// @Autowired // --> works
private TestService service;
mvn spring-boot:build-image -Pnative2
...
[INFO] Successfully built image 'docker.io/library/gdt:0.0.1-SNAPSHOT'
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:25 min
[INFO] Finished at: 2022-11-30T14:30:50+01:00
Run app:
graalDependencyTest % ./target/gdt
Invocation of REST endpoint ...
curl http://localhost:8080/foo
{"timestamp":"2022-11-30T13:34:36.062+00:00","status":500,"error":"Internal Server Error","path":"/foo"}%
... triggers NullPointerException when using @Resource
, but not when using @Autowired.
2022-11-30T14:32:52.710+01:00 ERROR 28966 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
at com.example.graaldependencytest.API.getFoo(API.java:32) ~[gdt:na]
at java.base@17.0.5/java.lang.reflect.Method.invoke(Method.java:568) ~[gdt:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:207) ~[gdt:6.0.2]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:152) ~[gdt:6.0.2]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[gdt:6.0.2]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884) ~[gdt:6.0.2]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[gdt:6.0.2]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[gdt:6.0.2]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1080) ~[gdt:6.0.2]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:973) ~[gdt:6.0.2]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1003) ~[gdt:6.0.2]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:895) ~[gdt:6.0.2]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:705) ~[gdt:6.0]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:880) ~[gdt:6.0.2]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814) ~[gdt:6.0]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:223) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[na:na]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[gdt:10.1.1]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[na:na]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[gdt:6.0.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[gdt:6.0.2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[na:na]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[gdt:6.0.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[gdt:6.0.2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[na:na]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[gdt:6.0.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[gdt:6.0.2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[na:na]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[na:na]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[na:na]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[gdt:10.1.1]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119) ~[na:na]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[gdt:10.1.1]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[na:na]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[na:na]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400) ~[na:na]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[gdt:10.1.1]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) ~[na:na]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1739) ~[na:na]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[gdt:10.1.1]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[na:na]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[na:na]
at java.base@17.0.5/java.lang.Thread.run(Thread.java:833) ~[gdt:na]
at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:775) ~[gdt:na]
at org.graalvm.nativeimage.builder/com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:203) ~[na:na]
environment:
java -version
openjdk version "17.0.5" 2022-10-18
OpenJDK Runtime Environment GraalVM CE 22.3.0 (build 17.0.5+8-jvmci-22.3-b08)
OpenJDK 64-Bit Server VM GraalVM CE 22.3.0 (build 17.0.5+8-jvmci-22.3-b08, mixed mode, sharing)
Apple Silicon M1 max
I am using the maven build profile native2, because using
mvn spring-boot:build-image -Pnative
leads to a stuck build / running endlessness (> 45 minutes).
I think Spring should remove jakarta.annotation.Resource
support(like removing EJB support).
Jakarta EE itself is cleaning up the dependency injection support in all specs, and trying to move all injection provider to CDI. Such as erasing the injection provider in JSF, REST etc.
The jakarta.annotation.Resource
(mainly for JNDI resource inject), JNDI Lookup, EJB are almost deprecated, I think they will not be updated in future.
Confirmed, the required reflection hints are missing when using @Resource
.
CommonAnnotationBeanPostProcessor
should probably be made AOT aware like AutowiredAnnotationBeanPostProcessor
is.
This is doable but more involved than expected, so I prefer to focus on the other issues for 6.0.5
.
As we try to empty 6.0.x
bucket, and given the various milestone date and summer PTO season, I am moving it back to 6.1.x
. Does not prevent to fix it in an upcoming 6.0 specific release, but let's decide when we have more visibility.