In my @Configuration
class I have dependendies like the following:
@Configuration
public class MyConfig {
@Resource(name = "firstDataSource")
private DataSource firstDataSource;
// more code
}
The dependency injection worked in Oracle JDK 8: firstDataSource
field was successfully injected with a non-null value.
Now I tried to run the application (with no modifications) in JDK 9. The result is that @Resource
does not trigger dependency injection anymore: everything annotated with this annotation remains null
.
What could be the reason for @Resource
to stop working?
Spring 4.0.9 is used in the project.
Here is a test project demonstrating the problem: https://github.com/rpuch/test-spring-injection-jdk9
It contains a single test: MainTest
which I run from my IDE. When I use JDK 8, it outputs
сен 29, 2017 10:45:13 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5f8ed237: startup date [Fri Sep 29 22:45:13 SAMT 2017]; root of context hierarchy
OK
But under JDK 9, it throws an exception during startup which is caused by the following:
Caused by: java.lang.IllegalStateException: bean1 is not injected
at Bean2.<init>(Bean2.java:7)
at Config2.bean2(Config2.java:16)
which happens when the dependency is not injected.
The java.xml.ws.annotation
being deprecated in jdk9 is possibly the cause of what you're facing. Since the annotation @Resource
is from the package javax.annotation
exported by the same module.
You might want to provide javatm-common-annotations as an upgradeable module for java.xml.ws.annotation
which exports the javax.annotation.
This standalone release of Java(TM) Common Annotations uses a Java Platform Module System "automatic" module name of java.annotation, to match the module name used in JDK 9.
The search on central suggests, you can use:-
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.1</version>
</dependency>
This runs fine on my machine with your shared code.
Also, a note about the code that you've shared. Since you're migrating to using JDK9, you should migrate to using latest springframework dependencies released as on 28-9-2017:-
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.0.RELEASE</version>
</dependency>
Edit : Do take a look at Roman's answer for an alternate to make use of --add-modules
in case you are not planning to migrate to the javaee
explosed module yet.
Adding a few missing details.
Spring @Resource
-driven injection only works when javax.annotation.Resource
is available at run time. Spring makes a check:
private static final boolean jsr250Present =
ClassUtils.isPresent("javax.annotation.Resource", AnnotationConfigUtils.class.getClassLoader());
and then uses that jsr250Present
variable to see whether @Resource
-based injection (and also @PostConstruct
/@PreDestroy
functionality) should be enabled.
In my case, under JDK 9, this class was not available in run time because it belongs to a separate module java.ws.xml.annotation
(separate from the basic java.base
module containing java.lang
and some other packages that is always available). To solve the problem, one of the following approaches may be taken:
javax.annotation-api
library to my application classpath, as @AlanBateman and @nullpointer suggested.java
may be instructed to add the module using a command line switch: --add-modules java.xml.ws.annotation
. This leaves the code intact.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With