Search code examples
androidrealmrealm-list

stackoverflow error while serializing generic class in GSON


I am trying to build a generic object named request which can hold request related to different entities.

For example , Request can be created for fitness class , employee class or contact class. Now below is the code to check whether we have any offline data exists or not. getNonSynced function will return the RealmResults of data those are not synced.

i am adding that realmResults into the request class's RealmList. once request is created i am converting it into json string using GSON and this is the point where my app gets crashed and throwing Caused by: java.lang.StackOverflowError: stack size 8MB

Function to get offline data and parse request

  public <T extends  RealmModel > void checkOfflineData(){


    Realm realm = Realm.getDefaultInstance();

    Set<Class<? extends RealmModel>> realmObjectClasses = realm.getConfiguration().getRealmObjectClasses();

    for(Class modelClass: realmObjectClasses) {

            // fetch non synced data 

            RealmResults realmResults = getNotSynced(realm,modelClass);
            if(realmResults !=null && realmResults.size() > 0){

                //build a request 
                Request<T> request = new Request<T>();
                RealmList<T> realmList = new RealmList<T>();
                //add results to list
                realmList.addAll(realmResults.subList(0, realmResults.size()));
                request.setRequestList(realmList);

            }
    }

    // Parsing using GSON data


    GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapter(Request.class, new RequestSerializer());
    Gson gson = builder.create();
    String data = gson.toJson(request);



}

Request Class

public class Request<T>  {

private RealmList<T> requestList;

public RealmList<T> getRequestList() {
    return requestList;
}

public void setRequestList(RealmList<T> requestList) {
    this.requestList = requestList;
}

}

This is probably happening at the time of GSON tries to serialize RealmList<T> requestList where it might be trying to find the concrete type. All i am seeking is the way to box the class and provide appropriate class type to T

Error

    07-17 13:04:00.177 6076-6076/com.org.connectedhealth W/System.err: Caused by: java.lang.StackOverflowError: stack size 8MB
        at java.lang.reflect.Field.get(Native Method)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.writeField(ReflectiveTypeAdapterFactory.java:138)
07-17 13:04:00.178 6076-6076/com.org.connectedhealth W/System.err:     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243)
        at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
        at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:208)
        at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:145)
        at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127)
07-17 13:04:00.179 6076-6076/com.org.connectedhealth W/System.err:     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
        at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
        at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
07-17 13:04:00.180 6076-6076/com.org.connectedhealth W/System.err:     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127)

I have tried few things here, if i am explicitly providing a type specific object then gson does not throw error.

      Request<T> request = new Request<T>();
      RealmList<T> realmList = new RealmList<T>();

      // explicitly providing fitness object 
      realmList.add((T)new Fitness());
      request.setRequestList(realmList);

so i think i need to explore a way to return realm result that has specific type.

 private <T extends RealmModel> RealmResults<T> getNotSynced(Realm realm , Class<T> modelClass) {

        RealmResults<T>  realmResults =null;
        try{

            realmResults= realm.where(modelClass).equalTo("syncInfo.syncStatus", false).findAll();
        }catch (Exception e){

            Log.e(TAG ,"Exception "+e.getMessage());

        }

        return  realmResults;
    }

Solution

  • by replacing following line to convert realm result into realm list , it started working because realmResults.subList(0, realmResults.size()) returns List<T> and copyFromRealm returns List<RealmModel>

    From

    realmList.addAll(realmResults.subList(0, realmResults.size()));
    

    To

    realmList.addAll(realm.copyFromRealm(realmResults));