Custom Annotations with Retrofit 2

André Tietz
5 min readMay 30, 2016

In some cases it would be nice to have custom annotation support in retrofit2. A year ago I started to write a library in which I needed this feature. In this article I will explain how to achieve and implement this.

UPDATE: There’s an updated and more detailed version of this article using Kotlin:

Why do you need custom annotations?

I guess in most cases you don’t need to use custom annotations, but interceptors. Since retrofit2 is based on okhttp, you can use interceptors (in retrofit 1.X this was supported by retrofit itself, too). But what does it do? Well, basically every request you call (using retrofit2 or plain okhttp) calls all setup interceptors before executing requests. The Interceptor is an interface which contains only one method to implement, called (surprise ^^) intercept, which get’s an object of Chain to proceed.

How to use Interceptor?

You can use Chain to execute

return chain.proceed(chain.request()); // returns Response

or modify request and execute

Request request = chain.request().newBuilder()
// modify the request as you need it

the next upcoming request.

This setup applies for ALL requests that run with the okhttp client in which you setup these interceptors.

Well, sometimes this is not enough, especially when you have runtime requirements for the modifications of the request.

Why did I came up with this?

Last year at droidcon Berlin I was thinking about a solution how to combine the android account manager and retrofit (1.9 back in the time).
Most of the requests are authenticated requests, meaning that they need to contain some kind of authentication token in the header. One would say now:

Well, just use interceptors for this and add it to the header.

I wanted to move this a step further. What if there are multiple different Token-Types (i.e. one for read-only, others for administration)? What if the user is not logged in yet? What if the token is not valid anymore? What if the token can be refreshed?
However, I decided to write an annotation that covers all this cases, so that the developer only needs to…