Skip to content

Commit

Permalink
Replaced Jackson by combination of GSON and AutoValue extension. (art…
Browse files Browse the repository at this point in the history
…em-zinnatullin#205)

* Added dependencies on gson and autovalue-gson libraries.

* Implemented GsonTypeAdapterFactory which spits out Item.GsonTypeAdapter generated by autovalue. Added test which ensures that Item type is registered within factory.

* Replaced EqualsVerifier in Item unit tests, which was failing against AutoValue_Item (it was trying to instantiate super type ($AutoValue_Type) with null arguments, as the result .equals() and .hascode() methods were throwing NPE. Suppressing warnings did not help.

* Replaced GsonTypeAdapterFactory with generated implementation from autovalue-gson. Removed redundant tests.
  • Loading branch information
arazabishov authored and artem-zinnatullin committed Oct 17, 2016
1 parent 4b3aeae commit 8b9389b
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 44 deletions.
11 changes: 7 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ apply plugin: 'com.github.ben-manes.versions'

paperwork {
set = [
gitSha: gitSha(),
buildDate: buildTime("dd-MM-yyyy HH:00:00 z", "UTC"),
gitSha : gitSha(),
buildDate: buildTime("dd-MM-yyyy HH:00:00 z", "UTC"),
]
}

Expand Down Expand Up @@ -119,14 +119,17 @@ dependencies {

compile libraries.okHttp
compile libraries.retrofit
compile libraries.retrofitJacksonConverter
compile libraries.retrofitGsonConverter
compile libraries.retrofitRxJavaAdapter
compile libraries.jacksonDataBind
compile libraries.gson

// Do not compile AutoValue dependencies to the app.
annotationProcessor libraries.autoValue
annotationProcessor libraries.autoValueGson

// Make AutoValue annotation visible to the compiler.
provided libraries.autoValue
provided libraries.autoValueGson

compile libraries.supportAnnotations
compile libraries.supportAppCompat
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.artemzin.qualitymatters.QualityMattersIntegrationRobolectricTestRunner;
import com.artemzin.qualitymatters.api.entities.Item;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;

import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -19,9 +19,9 @@ public class ItemTest {
// 2. Be sure that @JsonIgnore and similar annotations do not affect expected behavior (cc @karlicos).
@Test
public void fromJson() throws IOException {
ObjectMapper objectMapper = QualityMattersIntegrationRobolectricTestRunner.qualityMattersApp().applicationComponent().objectMapper();
Gson gson = QualityMattersIntegrationRobolectricTestRunner.qualityMattersApp().applicationComponent().gson();

Item item = objectMapper.readValue("{ " +
Item item = gson.fromJson("{ " +
"\"id\": \"test_id\", " +
"\"image_preview_url\": \"some_url\"," +
"\"title\": \"Test title\", " +
Expand All @@ -34,5 +34,4 @@ public void fromJson() throws IOException {
assertThat(item.title()).isEqualTo("Test title");
assertThat(item.shortDescription()).isEqualTo("Test short description");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import com.artemzin.qualitymatters.performance.AsyncJobsObserver;
import com.artemzin.qualitymatters.ui.activities.MainActivity;
import com.artemzin.qualitymatters.ui.fragments.ItemsFragment;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;

import javax.inject.Singleton;

Expand All @@ -36,9 +36,9 @@
})
public interface ApplicationComponent {

// Provide ObjectMapper from the real app to the tests without need in injection to the test.
// Provide Gson from the real app to the tests without need in injection to the test.
@NonNull
ObjectMapper objectMapper();
Gson gson();

// Provide QualityMattersRestApi from the real app to the tests without need in injection to the test.
@NonNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
import android.os.Looper;
import android.support.annotation.NonNull;

import com.artemzin.qualitymatters.models.QualityMattersImageLoader;
import com.artemzin.qualitymatters.models.PicassoImageLoader;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.artemzin.qualitymatters.models.QualityMattersImageLoader;
import com.artemzin.qualitymatters.other.EntityTypeAdapterFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapterFactory;
import com.jakewharton.picasso.OkHttp3Downloader;
import com.squareup.picasso.Picasso;

Expand Down Expand Up @@ -36,8 +39,15 @@ public Application provideQualityMattersApp() {
}

@Provides @NonNull @Singleton
public ObjectMapper provideObjectMapper() {
return new ObjectMapper();
public TypeAdapterFactory provideTypeAdapterFactory() {
return EntityTypeAdapterFactory.create();
}

@Provides @NonNull @Singleton
public Gson provideGson(TypeAdapterFactory typeAdapterFactory) {
return new GsonBuilder()
.registerTypeAdapterFactory(typeAdapterFactory)
.create();
}

@Provides @NonNull @Named(MAIN_THREAD_HANDLER) @Singleton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import android.support.annotation.NonNull;

import com.artemzin.qualitymatters.BuildConfig;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;

import javax.inject.Singleton;

Expand All @@ -12,7 +12,7 @@
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.jackson.JacksonConverterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

@Module
public class ApiModule {
Expand All @@ -30,11 +30,11 @@ public ChangeableBaseUrl provideChangeableBaseUrl() {
}

@Provides @NonNull @Singleton
public QualityMattersRestApi provideQualityMattersApi(@NonNull OkHttpClient okHttpClient, @NonNull ObjectMapper objectMapper, @NonNull ChangeableBaseUrl changeableBaseUrl) {
public QualityMattersRestApi provideQualityMattersApi(@NonNull OkHttpClient okHttpClient, @NonNull Gson gson, @NonNull ChangeableBaseUrl changeableBaseUrl) {
return new Retrofit.Builder()
.baseUrl(changeableBaseUrl)
.client(okHttpClient)
.addConverterFactory(JacksonConverterFactory.create(objectMapper))
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.validateEagerly(BuildConfig.DEBUG) // Fail early: check Retrofit configuration at creation time in Debug build.
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@

import android.support.annotation.NonNull;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.auto.value.AutoValue;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.annotations.SerializedName;

// This class is immutable, it has correctly implemented hashCode and equals.
// Thanks to AutoValue https://github.com/google/auto/tree/master/value.
@AutoValue
@JsonDeserialize(builder = AutoValue_Item.Builder.class)
public abstract class Item {

private static final String JSON_PROPERTY_ID = "id";
private static final String JSON_PROPERTY_IMAGE_PREVIEW_URL = "image_preview_url";
private static final String JSON_PROPERTY_TITLE = "title";
Expand All @@ -23,38 +22,39 @@ public static Builder builder() {
}

@NonNull
@JsonProperty(JSON_PROPERTY_ID)
public static TypeAdapter<Item> typeAdapter(Gson gson) {
return new AutoValue_Item.GsonTypeAdapter(gson);
}

@NonNull
@SerializedName(JSON_PROPERTY_ID)
public abstract String id();

@NonNull
@JsonProperty(JSON_PROPERTY_IMAGE_PREVIEW_URL)
@SerializedName(JSON_PROPERTY_IMAGE_PREVIEW_URL)
public abstract String imagePreviewUrl();

@NonNull
@JsonProperty(JSON_PROPERTY_TITLE)
@SerializedName(JSON_PROPERTY_TITLE)
public abstract String title();

@NonNull
@JsonProperty(JSON_PROPERTY_SHORT_DESCRIPTION)
@SerializedName(JSON_PROPERTY_SHORT_DESCRIPTION)
public abstract String shortDescription();

@AutoValue.Builder
public static abstract class Builder {

@NonNull
@JsonProperty(JSON_PROPERTY_ID)
public abstract Builder id(@NonNull String id);

@NonNull
@JsonProperty(JSON_PROPERTY_IMAGE_PREVIEW_URL)
public abstract Builder imagePreviewUrl(@NonNull String imagePreviewUrl);

@NonNull
@JsonProperty(JSON_PROPERTY_TITLE)
public abstract Builder title(@NonNull String title);

@NonNull
@JsonProperty(JSON_PROPERTY_SHORT_DESCRIPTION)
public abstract Builder shortDescription(@NonNull String shortDescription);

@NonNull
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.artemzin.qualitymatters.other;

import com.google.gson.TypeAdapterFactory;
import com.ryanharter.auto.value.gson.GsonTypeAdapterFactory;

@GsonTypeAdapterFactory
public abstract class EntityTypeAdapterFactory implements TypeAdapterFactory {

public static TypeAdapterFactory create() {
return new AutoValueGson_EntityTypeAdapterFactory();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@

import org.junit.Test;

import nl.jqno.equalsverifier.EqualsVerifier;
import nl.jqno.equalsverifier.Warning;
import static org.assertj.core.api.Java6Assertions.assertThat;

public class ItemTest {

@Test
public void hashCode_equals_shouldWorkCorrectly() {
EqualsVerifier
.forExamples(
Item.builder().id("id1").imagePreviewUrl("i1").title("Title1").shortDescription("s1").build(),
Item.builder().id("id2").imagePreviewUrl("i2").title("Title2").shortDescription("s2").build())
.suppress(Warning.NULL_FIELDS) // AutoValue checks nullability, EqualsVerifier does not expect that by default.
.verify();
public void equals_shouldWorkCorrectly() {
Item itemOne = Item.builder().id("id1").imagePreviewUrl("i1").title("Title1").shortDescription("s1").build();
Item itemTwo = Item.builder().id("id2").imagePreviewUrl("i2").title("Title2").shortDescription("s2").build();

assertThat(itemOne).isNotEqualTo(itemTwo);
}

@Test
public void hashcode_shouldWorkCorrectly() {
Item itemOne = Item.builder().id("id1").imagePreviewUrl("i1").title("Title1").shortDescription("s1").build();
Item itemOneCopy = Item.builder().id("id1").imagePreviewUrl("i1").title("Title1").shortDescription("s1").build();
Item itemTwo = Item.builder().id("id2").imagePreviewUrl("i2").title("Title2").shortDescription("s2").build();

assertThat(itemOne.hashCode()).isEqualTo(itemOneCopy.hashCode());
assertThat(itemOne.hashCode()).isNotEqualTo(itemTwo.hashCode());
}
}
10 changes: 6 additions & 4 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ ext.versions = [
errorProneCoreVersion : '2.0.9',
dexcountPlugin : '0.6.1',
versionsGradlePlugin : '0.13.0',
buildScan : '1.1.1',
buildScan : '1.1.1',

dagger : '2.6',

Expand All @@ -26,8 +26,9 @@ ext.versions = [
supportLibs : '23.1.1',
okHttp : '3.2.0',
retrofit : '2.0.0-beta4',
jackson : '2.8.1',
gson : '2.7',
autoValue : '1.2',
autoValueGson : '0.4.2',
butterKnife : '8.2.1',
picasso : '2.5.2',
picassoOkHttpDownloader : '1.0.2',
Expand Down Expand Up @@ -72,11 +73,12 @@ ext.libraries = [
okHttp : "com.squareup.okhttp3:okhttp:$versions.okHttp",
okHttpLoggingInterceptor: "com.squareup.okhttp3:logging-interceptor:$versions.okHttp",
retrofit : "com.squareup.retrofit2:retrofit:$versions.retrofit",
retrofitJacksonConverter: "com.squareup.retrofit2:converter-jackson:$versions.retrofit",
retrofitGsonConverter : "com.squareup.retrofit2:converter-gson:$versions.retrofit",
retrofitRxJavaAdapter : "com.squareup.retrofit2:adapter-rxjava:$versions.retrofit",
jacksonDataBind : "com.fasterxml.jackson.core:jackson-databind:$versions.jackson",
gson : "com.google.code.gson:gson:$versions.gson",

autoValue : "com.google.auto.value:auto-value:$versions.autoValue",
autoValueGson : "com.ryanharter.auto.value:auto-value-gson:$versions.autoValueGson",

supportAnnotations : "com.android.support:support-annotations:$versions.supportLibs",
supportAppCompat : "com.android.support:appcompat-v7:$versions.supportLibs",
Expand Down

0 comments on commit 8b9389b

Please sign in to comment.