Both of these checks are important, but you will not notice their effects until you simultaneously run several annotation processors in the same project. Let me explain.
If Javac fails to compile for any reason (for example, due to a lack of type declaration or parsing errors), it does not immediately end. Instead, it will collect as much information as possible about the error and try to display this information to the user in a meaningful way. In addition, if there are annotation processors, and the error was caused by the absence of a type or method declaration, Javac will try to start these processors and re-compile in the hope that they will generate the missing code. This is called multi-component compilation.
The compilation sequence will look like this:
- Primary round (possibly with code generation);
- A few additional rounds of creating code; new rounds will be executed until nothing is created by the annotation handlers;
- Last round; code generated during this round will not be processed by the annotation.
Each round is a full-blown attempt to compile code. Each round, with the exception of the last, will restart all code annotation processors previously created by annotation processors.
This wonderful sequence allows you to use the approach popularized by libraries such as Dagger2 and Android-Annotated-SQL: a link to a class that does not yet exist in the source code and allow the annotation processor to generate it at compile time:
// this would fail with compilation error in absence of Dagger2 // but annotation processor will generate the Dagger_DependencyFactory // class during compilation Dagger_DependencyFactory.inject(this);
Some people consider this iffy technology because it relies on the use of non-existent classes in the source code and closely links the source code to annotation processing (and does not work very well with IDE code completion). But the practice itself is legal and works as directed by the Javac developers.
So how does this all relate to the Spring Annotation Handler in your question?
TL DR: the code in your question does not work.
The correct way to use these methods is as follows:
for errorRaised :
- If your processor generates new public classes (which can be used ahead of time in user code, as described above), you should be super-robust: keep generating, ignore missing bits and mismatches when possible, and ignore
errorRaised . This ensures that you leave as few missing items as possible while Javac continues to report errors. - If your code does not generate new public classes (for example, since it only creates private-private classes, and other code will reflect them at runtime, see ButterKnife), then you should check
errorRaised ASAP, and exit immediately if it returns true . This will simplify your code and speed up erroneous compilation.
for processingOver :
- If the current round is not the last (
processingOver returns false), try to generate your result as much as possible; ignore missing types and methods in user code (suppose that some other annotation handlers can generate them in the next rounds). But try to generate as much as possible, if this may be necessary for other annotation processors. For example, if you run code generation for each class annotated with @Entity , you should @Entity over these classes and try to generate code for each, even if the previous classes have errors or missing methods. Personally, I simply wrap each individual generation unit in a try-catch and check processingOver : if it is false, ignore the errors and keep repeating annotations and generate the code. This allows Javac to break the circular dependencies between the code generated by various annotation processors, running them to complete satisfaction. - If the current round is not the last (
processingOver returns false), and some of the previous round annotations were not processed (I remember them whenever processing failed due to an exception), repeat processing on them. - If the current round is the last (
processingOver returns true), see if there are annotations that are still unprocessed. If yes, not compilation (only during the last round!)
The sequence above is for using processingOver .
Some annotation processors use processingOver slightly different way: they accumulate the code generated during each round and actually write it to Filer during the last round. This allows you to resolve dependencies on other processors, but does not allow other processors to find code created by "cautious" processors. This is a slightly nasty tactic, but if the generated code is not intended to be referenced elsewhere, I think that everything is in order.
And there are annotation processors like the aforementioned third-party Spring supporter: they misunderstand some things and use the monkey and key style APIs.
To get the best sense of everything, install Dagger2 and try to reference the classes created with Dagger in classes that are used by another annotation processor (preferably so that this processor resolves them). This will quickly show you how well these processors handle multi-million dollar compilation. Most of them will simply exclude Javac. Some of them spit out thousands of errors by populating the IDE error message buffers and clouding the compilation results. Very few will properly participate in multi-component compilation, but still spit out a lot of errors if they don't work.
The continue to generate code despite existing errors section is specifically designed to reduce the number of compilation errors recorded during failed compilation. Less missing classes = less missing declaration errors (hopefully). Also, do not create annotation handlers that prompt the user to reference the code they created. But you still have to cope with a situation where some kind of annotation processor generates code annotated with your annotations - unlike ads "ahead of schedule", users will expect it to just end.
Returning to the original question: since it is expected that the Spring configuration validation processor will not generate any code (I hope I did not look deeper into it), but should always report all errors in the verified configuration, it should work perfectly as follows: ignore errorRaised and put aside scan configuration as long as processingOver returns true: this will avoid reporting the same error several times during several rounds of compilation and allow annotation handlers generate new elements of the config ation.
Unfortunately, the processor in question looks abandoned (without commits since 2015), but the author is active on Github, so maybe you can report the problem to them.
At the same time, I suggest you learn from well-designed annotation processors such as Google Auto, Dagger2, or my tiny research project .