RxOAuth2: reactive OAuth approach for Android (Part 2)
TL;DR: with colleagues from Ackee we developed RxOauth2, an open source library to handle OAuth with RxJava streams. You may take a look at it directly or read this blog post (part 1 is here) to find out why and how we implemented it.
In Part 1, we were talking about the implementation of the core part of RxOauth2 library. In this part, we’d like to share our way to integrate the core logic into project REST API layer.
In almost every Ackee project we have so called ApiInteractor
, it is a layer between Retrofit API description (endpoints declaration layer) and repositories working with API requests. When using the first versions of RxOauth library, we had to separately wrap each of our requests with refresh token logic. We wanted to create a solution, which will integrate this logic to our API calls automatically by default.
It was Java time and annotation processors were on the peak of popularity. So we came up with a solution to generate a wrapper on top of ApiDescription
(Retrofit interface with endpoints declaration) during build time. We decided to take more general approach and created RxWrapper, a library that allows to generate a wrapper class around interface methods that return Observable
, Single
or Completable
. That wrapper then applies the custom Transformer
to each of those methods via compose()
operator. To exclude a method from applying the Transformer
, the NoCompose
annotation is used.
You may still explore and use RxWrapper library, but we stepped back from using it due to a couple of reasons:
- The wrapper is generated during build time, so the library user has to run the build at least once to be able to use the wrapper
- The wrapper is generated in Java, after Kotlin adoption we weren’t able to use its main features: optional values, default values or nullability
Rewriting the wrapper to Kotlin seemed more complex and we decided to look into another way to achieve required functionality. That’s how RxOauthCallAdapter
came into life.
To convert API Call
into arbitrary type Retrofit uses an interface called CallAdapter
. Retrofit itself has a couple of adapter implementations, for example RxJava2CallAdapter
allows us to work with API requests as RxJava2 streams. Initializing the CallAdapter
is done by setting the CallAdapter.Factory
to the Retrofit.Builder
when building the Retrofit
instance.
The cool thing about this decoupled architecture that it is possible to write your own CallAdapter.Factory
implementation and do whatever you want with requests handling. For example convert them to RxJava2 streams and wrap with OAuth logic. Unfortunately RxJava2CallAdapter
as well as its factory are final, that’s why we almost copied its functionality to create RxOauthCallAdapter
with RxOauthCallAdapterFactory
and added our wrapping. Now there is no need to work with each request manually or generate redundant classes, all the library user has to do is to add our custom factory to Retrofit client. Together with setting the OAuthInterceptor
it will look like this:
Now all our requests inside ApiDescription
will be wrapped with OAuth logic.
To exclude some requests from OAuth wrapping (registration, login etc.) you may use IgnoreAuth
annotation, which should be added to ApiDescription
functions:
Basically, that’s all about it. If you want to read about RxOAuth2 library usage or see its insides, it is available on Github.