Can I use compileOnly as a replacement for annotationProcessor in gradle?


My current understanding of annotation processor is that it refers to code that pre-parses a file looking for certain annotations, generating or changing other code based on that. It happens before the regular compilation phase of your project.

In gradle we typically use apt, kpt - and I've seen sometimes the use of annotationProcessor - to indicate that some dependency will be needed at "annotation processing time".

If the understand above is right, how does compileOnly differs from apt, kpt, etc?


As you've said, there are couple of annotation processing solutions in Gradle:

<ol><li>annotationProcessor facilities for Android</li> <li>apt for pure Java and Groovy</li> <li>kapt for Kotlin</li> </ol>

and so on. You can even implement one yourself! All of them use separate configuration for annotation processing.

Some of them, indeed, used to use compile classpath for processing. But this is not <em>semantically</em> corrent, it is not a "Gradle way". You should not mix your compile <em>time</em> only dependencies with the artifacts, required for you app to <em>run</em>. One simple scenario I can think of is creating fat JARs: most probably you do not want to pack and ship the processors you've used because it makes no sense! There may be other scenarios as well.

What you can do, thanks to Gradle's flexibility, is create another classpath (configuration) and use it only for annotation processing and then just forget about them. It is kind of semantics: you're telling Gradle (and other developers) that these dependencies are not required for you application to run. And this is the place where compileOnly differs from apt: compileOnly dependencies are mandatory for you code to operate, but they are meant to be <em>provided</em> by the environment. Will it be your application server, or plugin host system, or even you'll add them to the classpath manually - they will just <em>exist</em> on you runtime so you should not pack them with your distributable. But they are required to for your code to run. Some examples of compileOnly dependencies are Servlet API (your classes obviously extend and use them, but it will be provided by the server) or, if you're writing a Jenkins plugin, Jenkins core APIs (your plugin will be installed in a Jenkins where that core already exists). JDK itself is kind of compileOnly too. Annotation processors, on the contrary, are not meant to be used at runtime at all. They won't exist on classpath and they are not needed to run your app: they already generated some code that was compiled later.

Other implication of "mixing" configuration is performance. Just let me quote Android's documentation:


In previous versions of the plugin, dependencies on the compile classpath were automatically added to the processor classpath. That is, you could add an annotation processor to the compile classpath and it would work as expected. However, this causes a significant impact to performance by adding a large number of unnecessary dependencies to the processor.




  • CKEDITOR - Select span by its ID or CLASS and get its data attribute value
  • What does the auto c++ keyword do? [duplicate]
  • MethodNotAllowedHttpException while update record in laravel
  • Add dependency to .net core csproj file
  • Calculate number of days between two dates inside Django templates
  • Javascript increment operation order of evaluation
  • Converting object to Int pandas
  • file_get_contents Adding numbers from 2 text files
  • has_and_belongs_to_many relationship not associating both ways
  • Invalid date [dd/mm/yyyy] in safari? How to display in dd/mm/yyyy format using jquery
  • List (and connect to) Bluetooth devices from within iOS App
  • .Net how to set IsReadOnly for a property for a usercontrol
  • What is the purpose of set clock skew in wcf security mode settings
  • Mock request/post with mockito
  • Random number of FORM fields being prepared for database
  • Authorization Policies/Gates for Laravel 5.3 web app consuming own API w/ Passport
  • Encode string to Base64 in Inno Setup (Unicode Version of Inno Setup)
  • How do I hide and show the contents contents of a modal?
  • Insert inline image into Lotus Notes message
  • Using one probability set to generate another [duplicate]
  • Creating and managing two independent random number sequences
  • OpenCV::solvePNP() - Assertion failed
  • Bulk loading into PostgreSQL from a remote client
  • Arc gradients in Flutter?
  • Example of using Service Exists MSBuild task in Microsoft.Sdc.Tasks?
  • Facebook friend list in Facebook Android SDK 3.14
  • Unable to run testNG tests from maven
  • Multiple canvases (pages) in Fabric.js
  • Find all parks for a given zipcode with google maps
  • content must have a ListView whose id attribute is 'android.R.id.list'
  • playing mp3 from nsbundle
  • using maven pom while creating jar:test-jar some times it says JAR will be empty - no content was ma
  • Python 3x- Compression Makes File Bigger :(
  • Apple Mach-O Linker error (“duplicate symbol”)
  • Running R's aov() mixed effects model from Python using rpy2