问题
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.
回答1:
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());
//...
}
回答2:
As a workaround you could try to add the classpath you need to use via a command line argument -Xboothclasspath/a:path, the /a will append the value in path to the boot class path. You would need to add this as a command line option to the actual annotation processing run so in Eclipse that would be: Right click project, select properties, Java Compiler, Annotation Processing, click New in the table and add key -Xbootclasspath/a and the path to add as value. I'm afraid I haven't tried this for annotation processing but it's worth a try!
回答3:
My problem is that the properties files are not available via the classloader of the processor or via
Filer.getResource(...)
.
I'm not sure I'm understanding your problem. But maybe something here will help.
How can I make the source or classpath of this project available to the processor, so that I can load the properties files ?
You need to add the src/main/resources
as a "source folder" in Eclipse. First select Configure Build Path
in Eclipse on your Java project. Then choose the Source
tab and click on Add Folder
. You should be able to select the src/main/resources
folder and click Ok
. You should now see the src/main/resources
in the Source Folders list.
If you look into your target/classes
directory, you should see all of the files from the resources directory in there which lets you know that they were copied into the classpath correctly.
# files in the src main resources
> ls src/main/resources/x/y/z
jgroups_udp.xml
# should compile into target/classes
> ls target/classes/x/y/z
jgroups_udp.xml org
# and should show up in the jar
> -tvf target/project.jar
0 Thu Nov 03 18:50:00 EDT 2016 META-INF/
135 Thu Nov 03 18:49:58 EDT 2016 META-INF/MANIFEST.MF
...
3036 Thu Nov 03 18:49:36 EDT 2016 x/y/z/jgroups_udp.xml
Then in your code you can reference the file by doing the following. This will load the file from the top of the classpath. If it is in a subdir then you lead with:
InputStream stream =
getClass().getClassLoader().getResourceAsStream("x/y/z/jgroups_udp.xml");
Btw, if you were using maven, you would add something like the following to you pom.xml
:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
来源:https://stackoverflow.com/questions/18102444/cannot-load-resources-in-annotation-processor-not-on-classpath