How to get access to javax.annotation.Resource at run time in Java 9
Asked Answered
P

2

28

I have a test:

public class ResourceTest {
    @Test
    public void test() throws ClassNotFoundException {
        Class.forName("javax.annotation.Resource");
    }
}

It tries to access javax.annotation.Resource. In java 8 it worked, but in java 9 (I'm using Oracle JDK 9) it fails with ClassNotFoundException. As explained here Spring: @Resource injection stopped working under JDK9 , javax.annotation.Resource from the JDK is not available by default in Java 9.

I'm trying to get access to it using module descriptor:

module test {
    requires java.xml.ws.annotation;
    requires junit;
}

Here, I specifically request access to java.xml.ws.annotation module (which contains javax.annotation.Resource). But the test still fails.

When I remove that requires clause and add a dependency (as a library) which contains javax.annotations.Resource, it works:

    <dependency>
        <groupId>javax.annotation</groupId>
        <artifactId>javax.annotation-api</artifactId>
        <version>1.3.1</version>
    </dependency>

When I add them both (Maven dependency in pom.xml and requires java.xml.ws.annotation), compilation in IDEA fails with the following message:

the unnamed module reads package javax.annotation from both java.xml.ws.annotation and java.annotation

But Maven build still succeeds!

If I add java.xml.ws.annotation module via command line, it works (with no Maven dependency and with requires clause):

mvn clean test -DargLine="--add-modules java.xml.ws.annotation"

Do I do something wrong with my module description? How can I get access to JDK-supplied javax.annotation.Resource without command line switches?

The test project is available at https://github.com/rpuch/test-resource-jdk9

Proclus answered 30/9, 2017 at 10:51 Comment(4)
What happens when you just add the --add-modules argline and then requires <modulename>?Exenterate
@nullpointer The test successfully runs in such a case (the class is successfully found).Proclus
The java.xml.ws.annotation module is deprecated for removal. You should look at just depending on the standalone version, meaning requires java.annotation and the Maven dependency on javax.annotation/javax.annotation-api/1.3.1 as you have done. This eliminates the --add-modules from the usage too.Ossifrage
Possible duplicate of How to express dependency in maven on java ee features for transition to Java 9?Whitecap
E
42

Just to clear out some confusion here. The ways to work stated in the question by you are alternatives and should not be combined as you have already seen.

the unnamed module reads package javax.annotation from both java.xml.ws.annotation and java.annotation


So the way it would work is either:

You can use the compiler args to add modules

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.7.0</version>
    <configuration>
        <release>9</release>
        <compilerArgs>
            <arg>--add-modules</arg>
            <arg>java.xml.ws.annotation</arg>
        </compilerArgs>
    </configuration>
</plugin>

OR

Make use of the javax.xml.ws.annotation being an upgradeable module which is when you can make use of the dependency

<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.1</version>
</dependency>

Ideally this would be a preferrable option to stick to as the former is just an alternate to use the @Deprecated module marked forRemoval.


So the required clause by itself it not enough to get access to a module... is this true for all JDK-supplied modules (excluding java.base), or it is only true for deprecated modules?

No, the requires is just a part of declaration. [Think about this, prior to JDK 9 if you used a statement import some.foo.bar; in your class which was not added as a library(classpath) would that have worked?]. The module marked as required has to be on the modulepath for you to access it.


Update - The first option would not be supported any time longer with the use of JDK/11 or above wherein the JEP to Remove the Java EE and CORBA Modules is targetted.

Exenterate answered 30/9, 2017 at 11:8 Comment(8)
So the required clause by itself it not enough to get access to a module... is this true for all JDK-supplied modules (excluding java.base), or it is only true for deprecated modules?Proclus
Updated the answer fr this.Exenterate
First option worked for me. (Didn't try second option)Ochrea
The javax.annotation and other JavaEE classes are scheduled for removal in Java 11, per JEP-320, so the first option will no longer work in never versions.Lenette
@JoepWeijers Agreed. Would update the answer accordingly. :)Exenterate
@JoepWeijers The first version will work if you provide a dependency to javax.annotation-api as well.Whitecap
@nullpointer please, can you elaborate more option 2? What does it mean "Make use of the javax.xml.ws.annotation being an upgradeable module"? How would this be translated in the pom.xml?Pamilapammi
thanks so much for sharing this solution. For java 8 the second option (direct dependency) worked for me.Creole
P
2

For gradle build, adding the following to build.gradle works:

compile 'javax.annotation:jsr250-api:1.0'

tasks.withType(AbstractCompile) {
    options.compilerArgs += ["--add-modules", "java.xml.bind"]
}

tasks.withType(Test) {
    jvmArgs += ["--add-modules", "java.xml.bind"]
}
Pointsman answered 14/4, 2018 at 8:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.