I have an annotation processor which shall generate a enumeration with the keys defined by getter methods of an interface.
The interface resides in
MyProject/src/main/java/my.package.MyInterfaces.java.
I want to validate the properties files which reside in MyProject/src/main/resources/META-INF/resource-bundle/
if they do contain the keys defined in the generated enum.
My problem is that the properties files are not available via the classloader of the processor or via Filer.getResource(...).
How can I make the source or classpath of this project available to the processor, so that I can load the properties files ?
Now I have only the resources within the jar where the processor resides available. I did try to define -classpath and/or -sourcepath via eclipse Project/Properties/Java compiler/Annotation processing/Processor options but it did not work out.
Has anyone faced an issue like this, and can anyone give me a clue as to how I can make the resources available for the processor?
I do have the maven structure but do not use maven, because of old dependencies within the application. So maven is now not an option for me.
Eclipse 3.6 Helios Seems that
StandardLocation.SOURCE_PATH
andStandardLocation.CLASS_PATH
are not implemented in Filer#getResource(), so writing generated source or class files toSOURCE_PATH
orCLASS_PATH
seems not be possible, also accessing any files onSOURCE_PATH
andCLASS_PATH
*
Thanks.
The issue is the ClassLoader that is bound to the current thread (Thread.currentThread().getContextClassLoader()
) is not a URLClassLoader when Processor#process
is called. It appears to be a restricted class loader that does not allowing loading resources. This happens with javac, eclipse compiler, maven compiler, etc.
Luckily your processor class will have an appropriate ClassLoader bound to it (ie getClass().getClassLoader()
).
The problem is most utilities expect the correct ClassLoader to be bound to the thread (most notably the ServiceLoader and ResourceBundles).
Thus there is a work around. When your Processor executes you can rebind the ClassLoader to the current thread:
@Override
public boolean process(
Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
//...
}
EDIT:
I have feeling a large amount of people are having the problem of resources that are in src/main/resources
with Eclipse not loading them using the annotation processor Filer
(throws an exception).
And indeed it is a well known issue that Eclipse will not load target/classes
resources. The classpath hack I showed above may or may not work and was more for other libraries being used by the processor (as in they are already compiled with the resources).
The solution (if it could be called that) is to load the files like they are normal files. This requires guessing the project structure with some hacks.
OR
You can tell Eclipse users just to put the resources in src/main/java
.
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