Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.util.LinkedHashMap cannot be cast to DataList

I am trying to implement the server connections with retrofit library. Everything seems fine but when I receive the data on success callback it crashes with the below exception.

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to aandroid.com.retrofitframework.requestData.DataList
        at cuiserve.com.volleyframework.activity.RetrofitActivity$1.onDataReceived(RetrofitActivity.java:18)
        at cuiserve.com.volleyframework.httpConnection.ConnectionHelper.success(ConnectionHelper.java:44)
        at retrofit.CallbackRunnable$1.run(CallbackRunnable.java:45)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5001)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
        at dalvik.system.NativeStart.main(Native Method)

here is the activity class making the server calls

public class RetrofitActivity extends SuperActivity {


    private ConnectionHelper.ServerListener<DataList> httpListener = new ConnectionHelper.ServerListener<DataList>() {

        @Override
        public void onDataReceived(DataList data) {
            hideProgressBar();
            Log.d("ANSH",data.getBalance());
        }

        @Override
        public void onErrorReceived(String errorMsg) {
            hideProgressBar();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        showProgressBar();

        ConnectionHelper<DataList> helper = new ConnectionHelper<DataList>(HttpRequestConstant.LOGIN_REQUEST,httpListener);
        helper.getResponse();
    }

    @Override
    public View getLayoutResource() {
        return null;
    }

    @Override
    protected void internetAvailable() {

    }
}

ConnectionHelper.class making the request

public class ConnectionHelper<T> implements Callback<T> {


    private int requestType;
    private ServerListener<T> listener;

    public ConnectionHelper(int requestType, ServerListener listener) {
        this.requestType = requestType;
        this.listener = listener;
    }

    public void getResponse() {
        switch (requestType) {
            case HttpRequestConstant.LOGIN_REQUEST:
                IServerConnection<T> connection = restAdapter.create(IServerConnection.class);
                connection.login(this);
                break;
        }
    }


    RestAdapter restAdapter = new RestAdapter.Builder()
            .setEndpoint("http://www.json-generator.com/api")
            .setLogLevel(RestAdapter.LogLevel.FULL)
            .setConverter(new JacksonConverter(Mapper.get()))
            .build();

    @Override
    public void success(T t, Response response) {
        listener.onDataReceived(t);
        // success callback false here with the exception
        // as ClassCastException and says LinkedHashMap can not be cast to DataList(which i pass as class that the response has to be mapped to)
    }

    @Override
    public void failure(RetrofitError error) {

    }


    public interface ServerListener<T> {

        public void onDataReceived(T data);

        public void onErrorReceived(String errorMsg);

    }
}

The interface and the method with retrofit annotation

public interface IServerConnection<T> {

    @GET(HttpRequestConstant.JACKSON_FETCH)
    void login(Callback<T> cb);
}

The custom JacksonConverter which is my suspicion

public class JacksonConverter implements Converter {
    private ObjectMapper mapper = new ObjectMapper();

    public JacksonConverter(ObjectMapper objectMapper) {
        this.mapper = objectMapper;
    }

    @Override
    public Object fromBody(TypedInput body, Type type) throws ConversionException {
        JavaType javaType = mapper.getTypeFactory().constructType(type);

        try {
            return mapper.readValue(body.in(), javaType);
        } catch (IOException e) {
            throw new ConversionException(e);
        }
    }

    @Override
    public TypedOutput toBody(Object object) {
        try {
            String charset = "UTF-8";
            String json = mapper.writeValueAsString(object);
            return new JsonTypedOutput(json.getBytes(charset));
        } catch (IOException e) {
            throw new AssertionError(e);
        }
    }

    private static class JsonTypedOutput implements TypedOutput {
        private final byte[] jsonBytes;

        JsonTypedOutput(byte[] jsonBytes) {
            this.jsonBytes = jsonBytes;
        }

        @Override
        public String fileName() {
            return null;
        }

        @Override
        public String mimeType() {
            return "application/json; charset=UTF-8";
        }

        @Override
        public long length() {
            return jsonBytes.length;
        }

        @Override
        public void writeTo(OutputStream out) throws IOException {
            out.write(jsonBytes);
        }
    }
}

and the DataList

package cuiserve.com.volleyframework.requestData;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
 * Created by ansh on 5/4/15.
 */


@JsonIgnoreProperties(ignoreUnknown = true)
public class DataList extends SomeClass{

    private String _id;

    private int index;

    private String guid;

    private boolean isActive;

    private String balance;

    private String picture;

    private int age;

    public String get_id() {
        return _id;
    }

    public void set_id(String _id) {
        this._id = _id;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public String getGuid() {
        return guid;
    }

    public void setGuid(String guid) {
        this.guid = guid;
    }

    public boolean isActive() {
        return isActive;
    }

    public void setActive(boolean isActive) {
        this.isActive = isActive;
    }

    public String getBalance() {
        return balance;
    }

    public void setBalance(String balance) {
        this.balance = balance;
    }

    public String getPicture() {
        return picture;
    }

    public void setPicture(String picture) {
        this.picture = picture;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Now the problem is when i do it without using generics(which i have done in the code) things work fine and don't give any exception but in case of generics it fails.

Why am I getting LinkedHashMap classCastException where nothing is related to that in my code.Please help.

like image 911
anshul Avatar asked Jul 15 '15 09:07

anshul


People also ask

How do I cast a LinkedHashMap to a list?

To convert all values of the LinkedHashMap to a List using the values() method. The values() method of the LinkedHashMap class returns a Collection view of all the values contained in the map object. You can then use this collection to convert it to a List object.

How get values from LinkedHashMap?

You can convert all the keys of LinkedHashMap to a set using Keyset method and then convert the set to an array by using toArray method now using array index access the key and get the value from LinkedHashMap.

What is LinkedHashMap in Java?

The LinkedHashMap class of the Java collections framework provides the hash table and linked list implementation of the Map interface. The LinkedHashMap interface extends the HashMap class to store its entries in a hash table. It internally maintains a doubly-linked list among all of its entries to order its entries.

What is a class cast exception?

Introduction. ClassCastException is a runtime exception raised in Java when we try to improperly cast a class from one type to another. It's thrown to indicate that the code has attempted to cast an object to a related class, but of which it is not an instance.


Video Answer


1 Answers

By using a generic parameter the actual type information is completely lost to the runtime and cannot be inferred. It essentially ends up being the same as Object. When Gson sees that you want an Object type, it uses a Map to place the JSON information in. This way, if you re-serialize that object instance the data will be retained.

You cannot use generic interfaces with Retrofit. An exception has been added when you try to do this rather than letting it fail in this manner for the next release.

like image 82
Jake Wharton Avatar answered Oct 23 '22 12:10

Jake Wharton