Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrofit 2.0: getting response code 200 but not getting the desired data

A very disappointing feature of Retrofit 2.0 is that it does not exactly tell where it fails in parsing the response. Hence, In postman when I hit the request with same body, I get a login response as:

 {
    "result": "success",
    "response_code": 200,
    "data": {
        "id": "1",
        "display_name": "admin",
        "email": "[email protected]",
        "username": "admin",
        "access_token": "8daa8e02ca432e51ae90912fbf63eeea"
    }
}

But when I hit the exact same request with exactly the same body in Retrofit, I get a very peculiar response as: {protocol=http/1.1, code=200, message=OK, url=http://192.168.0.52/evidya/wp-api/v1/user/login}. Now I have gone through other related questions with above mentioned problem but none of them is working for me. Please Help. My code:

Retrofit API interface:

public interface eVidyaApi {

    @FormUrlEncoded
    @POST("user/login")
    Call<LoginResponse> loginUser(
            @HeaderMap Map<String, String> headers,
            @Field("email") String email,
            @Field("password") String password
    );
}

Login Function:

    public void login() {
        Log.d(TAG, "Login");
        if (!validate()) {
            onLoginFailed();
            return;
        }

        final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this, R.style.MyDialogTheme);
        progressDialog.setIndeterminate(true);
        progressDialog.setMessage("Authenticating...");
        progressDialog.show();

        String email = _emailText.getText().toString();
        String password = _passwordText.getText().toString();

        Log.d(TAG, "login: "+email+"  "+password);
        // TODO: Implement your own authentication logic here.
        Call<LoginResponse> loginResponseCall = evidya.loginUser(Common.getHeaders(), email, password);

        loginResponseCall.enqueue(new Callback<LoginResponse>() {
            @Override
            public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
                progressDialog.dismiss();
                if(!response.isSuccessful()){
                    Toast.makeText(LoginActivity.this, ""+response.message(), Toast.LENGTH_SHORT).show();
                    Log.d(TAG, "onResponse: fail "+response.code());
                    return;
                }

                Log.d(TAG, "onResponse: success"+response.code()+"  "+response);

                if(response.body()!=null){
                    String content="";
//                    _loginButton.setEnabled(false);
                    LoginResponse loginResponse = response.body();
                    content += "code:"+ response.code();
                    content += "token:"+ loginResponse.getData().getAccessToken();
                    content += "result"+ loginResponse.getResult();
                    content += "result"+ loginResponse.getData().getDisplayName();
//                    onLoginSuccess();
                    Log.d(TAG, "onResponse: login res"+content);
                } else {
                    Toast.makeText(LoginActivity.this, "Invalid response from server", Toast.LENGTH_SHORT).show();
                }

            }

            @Override
            public void onFailure(Call<LoginResponse> call, Throwable t) {
                progressDialog.dismiss();
                Toast.makeText(LoginActivity.this, "Cannot fetch request", Toast.LENGTH_SHORT).show();

            }
        });
    }

LoginResponse.java

package com.example.evidya.Retrofit.Model.LoginModel;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class LoginResponse {

    @SerializedName("result")
    @Expose
    private String result;
    @SerializedName("response_code")
    @Expose
    private Integer responseCode;
    @SerializedName("data")
    @Expose
    private Data data;

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public Integer getResponseCode() {
        return responseCode;
    }

    public void setResponseCode(Integer responseCode) {
        this.responseCode = responseCode;
    }

    public Data getData() {
        return data;
    }

    public void setData(Data data) {
        this.data = data;
    }

}

Data.java

package com.example.evidya.Retrofit.Model.LoginModel;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Data {

    @SerializedName("id")
    @Expose
    private String id;
    @SerializedName("display_name")
    @Expose
    private String displayName;
    @SerializedName("email")
    @Expose
    private String email;
    @SerializedName("username")
    @Expose
    private String username;
    @SerializedName("access_token")
    @Expose
    private String accessToken;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }

}

My Logging(ok hhttp), when clicking the login button with wrong details:

enter image description here

My Logging(ok hhttp), when clicking the login button with CORRECT details:

enter image description here Solution:

Basically the problem was that I was using Log.d(TAG, "onResponse: success"+response.code()+" "+response); to check the response in the onresponse callback. Whereas all I should have done is to not get stuck there and check the value of the loginResponse object (from LoginResponse loginResponse = response.body();). Because response.body actually stores the reponse in object form. This is how things work in retrofit.

like image 766
Shikhar Avatar asked Apr 02 '19 05:04

Shikhar


1 Answers

enter image description here

As per your log, API calls properly. It also responds. but the issue is API authentication is failed from your back end. Add log on your web service and check. From the application side, it is working fine. this is not an issue of Retrofit.

Update your onResponse() with below and run application. then test and let me know what message you get.

if(response.body()!=null){
                LoginResponse loginResponse = response.body();
                String content="";
                if (response.body().getResponseCode()==200){
                    content+= loginResponse.getData().getAccessToken();
                    content+= loginResponse.getData().getDisplayName();
                    content+= loginResponse.getData().getEmail();
                    content+= loginResponse.getData().getId();
                    content+= loginResponse.getData().getUsername();
                }else{
                    content+=loginResponse.getData().getMsg();
                }

                Log.d(TAG, "onResponse: login res"+content);
            } else {
                Toast.makeText(LoginActivity.this, "Invalid response from server", Toast.LENGTH_SHORT).show();
            }

Below code in Data.java

 @SerializedName("msg")
        @Expose
        private String msg;
        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }
like image 88
Samir Bhatt Avatar answered Sep 17 '22 10:09

Samir Bhatt