Avoid loading a transitively dependent module

Viewed 628

I am compiling my legacy source code using JDK 9.0.1 as follows:

javac --add-modules=java.base,java.xml.ws -cp lib\jsr305.jar;lib\javax.annotation-api-1.2.jar TestJava.java

It gives an error because the annotations defined in jsr305.jar are not visible due to split module issue. The error is as follows:

TestJava.java:3: error: cannot find symbol
import javax.annotation.Nonnull;
                       ^
  symbol:   class Nonnull
  location: package javax.annotation

Here the module java.xml.ws.annotation is getting loaded since it is required for java.xml.ws. So it is ignoring the types in jsr305.jar. I don't want this module to be loaded but refer all its annotation types from javax.annotation-api-1.2.jar. I don't want to do --patch-module either because it would break in future releases.

If I use --limit-module=java.xml.ws.annotation it gives the same error. If I remove java.xml.ws from -add-modules, it compiles successfully but I need to export few APIs from it so can't remove it. Is there any way I can load module java.xml.ws but not java.xml.ws.annotation?

EDIT : I think I have added some confusion by giving an example of split between java.xml.ws.annotaion and jsr305.jar. Though it's my actual problem, I am more interested in knowing - can I avoid loading a transitively dependent module, say loading java.xml.ws without loading java.xml.ws.annotation? As per my understanding in JEP 261 it says,

--limit-modules <module>(,<module>)*

where <module> is a module name. The effect of this option is to limit the observable modules to those in the transitive closure of the named modules plus the main module, if any, plus any further modules specified via the --add-modules option.

So, why isn't --limit-module preventing java.xml.ws.annotation from loading?

1 Answers

I know of no way to prevent resolution of a transitive dependency.

Short-term fix

You should be able to make it work by patching the module with --patch-module java.xml.ws=lib\jsr305.jar:lib\javax.annotation-api-1.2.jar. My opinion: If you just want to get your build working on Java 9, that is a good choice. It's a little dubious but still acceptable if you want to use it in production.

If you're worried about long-term compatibility:

  • I don't think --patch-module will disappear any time soon - do you have a source for that?
  • I'm pretty sure java.xml.ws will be removed quite soon - it is already deprecated for removal.

In your place I'd worry about the module more than about patching it.

Long-term solution

So for a long-term solution you should remove your dependency on java.xml.ws. JDK-8189188 has a section on this (with lots of links that I was too lazy to copy):

The Reference Implementations (RIs) of JAX-WS and JAXB are a good starting point because they are complete replacements for the java.xml.ws and java.xml.bind modules in JDK 9. The RIs are available as Maven artifacts: (note that they must be deployed on the classpath)

  • com.sun.xml.ws : jaxws-ri (JAX-WS, plus SAAJ and Web Services Metadata)
  • com.sun.xml.bind : jaxb-ri (JAXB)

The tools for JAX-WS and JAXB are also available as Maven artifacts:

  • wsgen and wsimport: com.sun.xml.ws : jaxws-tools, plus tool scripts
  • schemagen and xjc: com.sun.xml.bind : jaxb-jxc and com.sun.xml.bind : jaxb-xjc, plus tool scripts

There are also Maven artifacts that contain just the APIs of the Java EE technologies:

  • javax.xml.ws : jaxws-api (JAX-WS, plus javax.xml.soap : javax.xml.soap-api for SAAJ and javax.xml : webservices-api for Web Services Metadata)
  • javax.xml.bind : jaxb-api (JAXB)
  • javax.activation : javax.activation-api (JAF)
  • javax.annotation : javax.annotation-api (Common Annotations)

Adding either the API JARs or the reference implementations to your class path together with all other javax.annotation-related JARs will work because all class path content ends up in the same module (the unnamed one) and thus split packages are no problem there.

Related