Issue
To register a service provider in a Java 11 the following "provides" module-info entry can be used:
module com.mycompany.mylib {
provides ServiceInterface with ServiceImpl;
}
With annotation processors this doesn't seem to work, however. (The special thing with annotation processors is that it's the compiler which should pick up the implementation during compile time rather than the application during runtime.)
To test this out, I've created some SSCCEs on GitHub.
There are 2 modules:
java11-sample-annotation-processor
: provides the@Foo
annotation and theFooApplicationProcessor
java11-sample-lib
: provides 2 sample classes, both using the@Foo
annotation
Expected output: in the java11-sample-lib
JAR there should be a foo.txt
file
The version in the master branch is the one that works:
- Java 11
- no
module-info
used - annotation processor registration in
src/main/resources/META-INF/services/javax.annotation.processing.Processor
In the following versions the foo.txt
file is not generated:
In the registration-in-module-info branch I've changed the 2 libs to Java 11 modules with module-info. The annotation processor is here registered in the module-info:
import com.github.puce77.java11annotationprocessortest.annotation.impl.FooApplicationProcessor;
module com.github.puce77.java11annotationprocessortest.annotation {
exports com.github.puce77.java11annotationprocessortest.annotation;
provides javax.annotation.processing.Processor with FooApplicationProcessor;
requires java.compiler;
}
The registration-in-module-info-moduleAndPkg branch is a slight variation, where I specified the target module and target package (hardcoded) rather than the root package.
In the registration-meta-inf branch still both have a module-info but the annotation processor is registered in src/main/resources/META-INF/services/javax.annotation.processing.Processor
rather than in the module-info (in case the compiler can not work with provides statements in the module-info!?)
In the only-one-module branch I've removed the module-info from the java11-sample-annotation-processor
again. The annotation processor is registered in src/main/resources/META-INF/services/javax.annotation.processing.Processor
.
So my question: how can I configure an annotation processor when working with Java 11 modules?
Solution
It used to be that annotation processors were automatically detected when placed on the class-path during compilation. You can see this from the documentation of javac
:
--class-path
path,-classpath
path, or-cp
pathSpecifies where to find user class files and annotation processors [emphasis added]. This class path overrides the user class path in the
CLASSPATH
environment variable.
- If
--class-path
,-classpath
, or-cp
are not specified, then the user class path is the value of theCLASSPATH
environment variable, if that is set, or else the current directory.- If not compiling code for modules, if the
--source-path
or-sourcepath
option is not specified, then the user class path is also searched for source files.- If the
-processorpath
option is not specified, then the class path is also searched for annotation processors [emphasis added].[...]
--processor-path
path or-processorpath
pathSpecifies where to find annotation processors. If this option is not used, then the class path is searched for processors [emphasis added].
And this is still the case as long as you're using the class-path. This is not the case, however, when using the module-path. For modular annotation processors to be detected you have to explicitly point to them with another option:
--module-path
path or-p
pathSpecifies where to find application modules.
[...]
--processor-module-path
pathSpecifies the module path used for finding annotation processors.
No mention of the module-path being used to automatically detect annotation processors.
Answered By - Slaw
Answer Checked By - Senaida (JavaFixing Volunteer)