Monday, February 2, 2015

gce2retrofit, a gradle plugin

I am working on an Android app that uses Retrofit to talk to a Google Cloud Endpoints (GCE) server. Initially I was writing the Retrofit interfaces and models by hand, but then I found out that GCE servers serve a discovery document describing all its endpoints in JSON. So I started working on a tool to generate the Retrofit Java files automatically from the JSON document.

JavaWriter

I used JavaWriter (predecessor to JavaPoet) for code generation because I have this vague idea that if I do it in Java I can make it a gradle plugin. My first iteration is a jar file that can be run from the command-line, taking the discovery JSON file as an argument, and writes the Java files to the src/main/java directory to be checked in. This is a major time saver since I don't have to manually write all the Retrofit classes and interfaces every time the server updates.

Gradle plugin

To make it even easier, I want the code generation to be a part of the build process. I want the GCE discovery JSON file to be the source of truth, generating the Retrofit Java files when it gets updated. I have never written a Gradle plugin before, so I went through the tutorial to get a basic understanding.

I had difficulty getting Android Studio to recognize the generated files until I found another code generation gradle plugin that works with Android: Paraphrase.

Points to note

In the gradle task:

  • Use @InputDirectory to specify what triggers an incremental build.
  • Use @OutputDirectory to create the output directory on demand.

In the gradle plugin:

  • Use project.plugins.hasPlugin to determine if it is a Java project or an Android project.
  • Use variant.registerJavaGeneratingTask to make Android Studio recognize the generated files.

Push to Sonatype Nexus

Once my plugin is ready I need to publish it. I want to push a snapshot first, so I looked into Sonatype Nexus. There seems to be many different ways to do it, and I was at analysis paralysis for weeks. Finally I turned to Twitter and Google+ to ask for help, and pushed the snapshot with the maven and com.bmuschko.nexus plugins.

Try it

If you use Google Cloud Endpoint with Retrofit, please try the plugin and file issues if you encounter any. Instructions and source code here: https://github.com/chiuki/gce2retrofit.