Home Java OData+ RxJava+ Retrofit 2for android application

OData+ RxJava+ Retrofit 2for android application

by admin

I have faced with a hitherto unseen problem on my project.I had to read the documentation and in this article I will tell you how to use RxJava and Retrofit 2 – you can solve the problem of creating a client Odata For android application.
Thank you very much Jake Wharton For creating such comfortable tools.

Welcome to the world of magic

We have an application that by protocol Odata should fetch data from server, display it in lists which should be loaded as you scroll and send user-created data to the server. It’s a trivial task, but it’s not so easy, what works on Java doesn’t want to work on android in the same way.
And the libraries and documentation on the Odata Only from Apache – Olingo and Microsoft in C#.
In this article, the protocol Odata I won’t look into it, there’s a very good documentation by Microsoft and I’ll leave the links at the end of the article.
Here is a short definition from Wiki Open_Data_Protocol
Open Data Protocol (OData)

The Open Data Protocol (OData) is an open web protocol for querying and updating data. The protocol allows you to perform operations on resources using HTTP commands as queries and receive responses in XML or JSON formats.
As of version 4.0, OData is an open standard approved by OASIS.

And this is where the fun part comes in, Odata – is a kind of SQL in REST API and for dynamically created data it’s perfect.
But we have a strictly typed language and without knowing the model – data processing and storage creates quite a challenge.
The solution of which cannot be typical and repeatedly described on the net.
I’ll say even more, other than these links to documentation on the web – everything is bad on the topic.
Now let’s do some magic :
Creating a service to work with the network
Let’s use Retrofit 2 and related company products Square
Add dependencies to the build.gradle file

// Networkimplementation 'com.squareup.retrofit2:retrofit:2.7.1' // Retrofit 2implementation itself 'com.squareup.retrofit2:converter-gson:2.7.1' // Converter for working with JSONimplementation 'com.squareup.okhttp3:logging-interceptor:4.3.1' // Request interceptorimplementation 'com.squareup.retrofit2:adapter-rxjava2:2.7.1' // Adapter for working with RxJavaimplementation 'com.squareup.okhttp3:okhttp:4.3.1' // OkHttp is an HTTP client

listing 1
All these dependencies are the most powerful networking library in Java.
Describe work with Retrofit 2 I do not see the point, here is a good manual : Using Retrofit 2in an Android app
We create a NetworkService class:

public class NetworkService {private static final String TAG = "NetworkService";private static final NetworkServicemInstance = new NetworkService();private String mToken;private Retrofit mRetrofit;public static NetworkService getInstance() {return mInstance;}private NetworkService() {RxJava2CallAdapterFactory rxAdapter =RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io());HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);OkHttpClient.Builder okHttpClient =new OkHttpClient.Builder().addInterceptor(interceptor).addInterceptor(chain -> {Request newRequest =chain.request().newBuilder().addHeader("Accept", "application/json, text/plain, */*").addHeader("Content-Type", "application/json;odata.metadata=minimal").addHeader("Authorization", mToken).build();return chain.proceed(newRequest);});Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create();mRetrofit = new Retrofit.Builder().baseUrl(Const.BASE_URL).addConverterFactory(GsonConverterFactory.create(gson)).addCallAdapterFactory(rxAdapter).client(okHttpClient.build()).build();}public ApiService getNetworkClient(){return mRetrofit.create(ApiService.class);}}

listing 2
Create API:

public interface ApiService {// Make a query without conditions@GET("odata/product")Observable<List<ProductsDto> > getProducts();}

listing 3
And create some kind of controller to pull queries :

public class ProductsController {private ApiService mApiService;private List<ProductsDto> listProducts;private Gson gson;public ProductsController() {mApiService = App.getNetworkService().getNetworkClient();listProducts = new ArrayList<> ();gson = new Gson();}public void productsBtnClick() {mApiService.getProducts().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new DisposableObserver<List<ProductsDto> > () {@Overridepublic void onNext(List<ProductsDto> products) {listProducts.addAll(listProducts);}@Overridepublic void onError(Throwable e) {}@Overridepublic void onComplete() {}});}

listing 4
So, the server stores a data model Poduct, which has some parameters and attributes. All the data is in JSON format and we need POJO class to work.
I recommend setting the level of intercept details in HttpLoggingInterceptor – Level.BODY.
Making a request listing 4 to draw out the data structure as much as possible and the answer will be in this format approximately :

// there is a list of top level entities// in JSON format{"@odata.context":"https://example.xxx/api/odata/$metadata", "value":[{"name":"product", "kind":"EntitySet", "url":"product" // product}, {"name":"blogs", "kind":"EntitySet", "url":"blogs" // blogs}, {"name":"posts", "kind":"EntitySet", "url":"posts" // posts}, {"name":"comments", "kind":"EntitySet", "url":"comments" // comments}, {"name":"rates", "kind":"EntitySet", "url":"rates" // ratings}]}

listing 5
And already on the basis of these data you can form a request for further data manipulation.
So, this is a full-fledged object with some kind of behavior and attributes, to get this information when creating a query you need to add conditions, based on which we get our DataSource without reinventing the wheel and without bolting crutches to it.

Culmination and puppyish delight in the comfort of the instrument

And here is the moment of truth, the power, strength and simplicity of the library Retrofit 2 You can now get properties using the service document Odata :

// You can get the properties of the product entity@GET("odata/product?$filter=Id eq 111$expand=dateReading($orderby=Date desc")Observable<List<ProductsDto> > getProducts();// Or properties of the blogs entity@GET("odata/blogs?$orderby=Date desc")Observable<List<BlogsDto> > getBlogs();// And you can already formulate your request according to your needs@GET("odata/product?$filter=((Id eq 19) and (Name eq 'Available')) and ((Status eq 'OPEN') or ((Status eq 'CLOSED') and (Date ge 2020-02-13T06:39:48Z)))$orderby=Status asc, Date desc$top=10$expand=AuthorId, CategoryId($expand=weight)$count=true")Observable<List<ProductsDto> > getProducts();// This query will output the exact information selected by the conditions, //but it is clearly out of a reasonable range.// Fixing :@GETObservable<List<ProductsDto> > getProducts(@Url String url);

listing 6
That’s the power of a bogatyr library Retrofit 2 Dynamic Url takes care of all this mass of parameters, which you can play with in code as much as you can imagine.
It would look something like this :

private void buttonGetProduct() {// Here you can do everything with stringsString one = "odata/product?$filter=Id eq ";String id = "777";String tree = "$expand=dateReading($orderby=Date desc)";String url = one + id + tree;mApiService.getProduct(url).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new DisposableObserver<List<ProductDto> > () {@Overridepublic void onNext(List<ProductDto> products) {// This is where we get what we are looking for, although the data is in the JSON format, // but there are plenty of converters, so this is not a problemmProductsDto.addAll(countersDtos);}@Overridepublic void onError(Throwable e) {}@Overridepublic void onComplete() {}});}

listing 7

Results

It was a rewarding experience that I’m in a hurry to share, to me at one time this article would have really taken away a lot of problems and questions.
In the article I did not go into unnecessary detail on Retrofit 2 and OData and have provided links to the documentation if you need to delve deeper.
I can’t give you the full version of the code, sorry about that, it’s a commercial product.
And, as promised, links :
Microsoft documentation: Open Data Protocol
Documentation OData 4.0 Java Library
Creating full-featured Internet applications using Open Data Protocol

You may also like