Java Basics for Retrofit — Annotations

A lot of readers on our Retrofit series are just starting out with developing software or are new to Java/Android. We're really happy to welcome all new developers! We've received many questions, which were caused by implementing apps with Retrofit, but not actually specific to Retrofit. Consequently, we decided to start a mini-series to explain some Java and network basics in preparation for your extensive use of Retrofit!

Today's topic will be Java annotations. Retrofit uses a lot of method and parameter annotations to add meta information when describing endpoints, request headers and payloads. In this tutorial you'll learn what all of that means.

Retrofit Series Overview

Java Annotations

As you know, Java uses certain keywords to describe classes, methods and variables. For example, a private keyword tells you that the method can only be accessed within the class. When a method has a void return type, it won't return anything. These are structured standard information about your Java code. However, what if you need to supply more structured information, which can't be described with the default keywords?

Annotations are a way to provide additional information (metadata) about packages, interfaces, classes, methods, variables or even parameters. They're very easy to recognize, because they're always directly before Java keywords and start with an @. Java only supplies a handful of annotations (e.g. @Override and @Deprecated), but supports the creation of custom annotations for a variety of use cases. They can be significantly different in their impact on your project.

For example, you might have used annotations to tell a compiler to ignore warnings (@SuppressWarnings()). Here, the annotation is only available for the compile process. In other words, the annotation has no effect on the code or during the runtime of the application, but the compiler will change its behavior based on the annotation.

A second kind of annotation is more active during the compiling of the project and adds additional resources or code. Android developer rookies might have seen it with ButterKnife. ButterKnife provides a @BindView annotation, which will generate the long findViewById() statements for you. This kind of annotation makes your code cleaner and a few things easier for you as the developer. However, during the runtime of your application they’re gone, since they were processed into regular Java statements.

Lastly, and especially on Android, there are a lot of libraries which use annotations to further enhance methods and parameters during the runtime of the app. Retrofit is only one out of many libraries, which uses runtime annotations. In some advanced Retrofit tutorials we even introduce our own runtime annotations to improve our code base.

Retrofit's Method Annotations

You've learned that Retrofit uses runtime annotations to further describe methods and parameters, but what does that mean in particular? One of the developer's tasks when working with Retrofit is to describe API endpoints. Let's look at an imaginary user API. Your (simplified) interface might have three methods like:

public interface UserApi {

    public UserInfo getUserInfo();

    public UserInfo createUser(UserInfo newUser);

    public void deleteUser(UserInfo deleteUser); 

}

Retrofit needs to generate the code for executing the network requests out of this code. However, there is no clean way of knowing what kind of HTTP method the API expects. Of course, Retrofit could ask you during the request creation (like retrofit.post() or retrofit.get()), but this clutters your application code with information about your API. The reason we write the API interface is to separate your application code from your API implementation. Consequently, we need to enhance our three API methods with an appropriate annotation for the API HTTP method:

public interface UserApi {

    @GET
    public UserInfo getUserInfo();

    @POST
    public UserInfo createUser(UserInfo newUser);

    @DELETE
    public void deleteUser(UserInfo deleteUser); 

}

The @GET, @POST, @DELETE annotations are actual annotations from the Retrofit library. They're required for all API interface methods, since Retrofit needs to know this additional structured data.

Enhancing Annotations with Data

Nevertheless, sometimes the annotation itself is still not enough metadata. Java offers the option to include further data to the annotation. For example, Retrofit's HTTP method annotations allow you to pass the URL, where this request is supposed to go: @GET("http://futurestud.io/api/user/norman"). In this case, we're enhancing our annotation with even more information. We passed a String directly to the annotation. In other libraries and annotations you'll come across the option to pass multiple values. Then you'll have to specify which parameters describes what:

@FutureStudioTutorial(
    title = "Java Basics for Retrofit - Annotations",
    url = "https://futurestud.io/tutorials/java-basics-for-retrofit-annotations"
)

This annotation supports multiple String parameters, but now we need to name them. An alternative is to use multiple annotations at once:

@FutureStudioTutorialTitle("Java Basics for Retrofit - Annotations")
@FutureStudioTutorialURL("https://futurestud.io/tutorials/java-basics-for-retrofit-annotations")

Retrofit's Parameter Annotations

You can chain the same or different annotations as much as you want. Retrofit utilizes this in their API interface declarations. Back to the examples of our Retrofit annotations: so far, all of these were examples of method annotations, but Retrofit also uses parameter annotations. For example, in the above example of createUser(UserInfo newUser), how is Retrofit supposed to send the data? As a request body or maybe form-urlencoded? Well, as you guessed it, you should clarify this for Retrofit with an annotation!

public interface UserApi {

    @POST
    public UserInfo createUser(@Body UserInfo newUser);

}

The @Body annotation is for the newUser object and describes how the data should be send to the server. The purpose of the annotation is to make it much cleaner and easier for us developers to describe the request payload.

It's important to know that all of the annotations we've introduced in this section are already prepared by Retrofit. You can find them in the retrofit2.http. package.

Custom Annotations

If you're developing an app or a library, it might make sense to create your own annotation. Hopefully, you've seen how helpful they can be to your code in the previous section. The good news is that it's quite easy to create annotations.

Outlook

In this tutorial you've learned what annotations are and what they can be used for. Additionally, you've seen them in action in Retrofit. Annotations are still underutilized and can really improve your code base. Keep your eyes open and don't be afraid to implement your own annotation!

If you've feedback or a question, let us know in the comments or on twitter @futurestud_io.

Make it rock & enjoy coding!

Explore the Library

Find interesting tutorials and solutions for your problems.

Miscellaneous