1

I'm implementing a simple login to an endpoints using Retrofit2. Things work fine when the user credentials are correct but break when I try to enter a non valid data. I'm trying to handle the errors when the user is not found but I can't find a way to do that. The error response looks like:

{
    "0": [
        "erreur",
        "statut"
    ],
    "erreur": "Erreur, connexion echoue.",
    "statut": "KO"
}

This response has status 200 despite being an error.

The app is crashing with NPE in the LoginRepository where I'm trying to save user's data to SharedPreferences because the error result is not handled so the app threat any response as Successful.

The sample provides a Result class which doesn't seem to work for my use case because the response is always successful:

   public class Result<T> {
    // hide the private constructor to limit subclass types (Success, Error)
    private Result() {
    }

    @Override
    public String toString() {
        if (this instanceof Result.Success) {
            Result.Success success = (Result.Success) this;
            return "Success[data=" + success.getData().toString() + "]";
        } else if (this instanceof Result.Error) {
            Result.Error error = (Result.Error) this;
            return "Error[exception=" + error.getError().toString() + "]";
        }
        return "";
    }

    // Success sub-class
    public final static class Success<T> extends Result {
        private T data;

        public Success(T data) {
            this.data = data;
        }
        public T getData() {
            return this.data;
        }
    }

    // Error sub-class
    public final static class Error extends Result {
        private Exception error;


        public Error(Exception error) {
            this.error = error;
        }

        public Exception getError() {
            return this.error;
        }

    }
}

And here is how I'm handling the login in the LoginRepository:

public Result<LoggedInUser> login(String username, String password) {
    // handle login
    Result<LoggedInUser> result = dataSource.login(username, password);
    if (result instanceof Result.Success) {
        setLoggedInUser(((Result.Success<LoggedInUser>) result).getData());
    }

    return result;
}

Note: I don't have access to the server. I use Gson as converter

The login activity sample I used can be found here

UPDATE:

Login successful with valid credentials:

enter image description here

esQmo_
  • 1,464
  • 3
  • 18
  • 43
  • 1
    I think this will fixed from the backend or change your Loggedinuser model as a responsebody. https://stackoverflow.com/questions/37337516/okhttp-new-jsonobject-from-response Also check this answer – Vijendra patidar May 09 '20 at 16:34
  • They are handling JSON parsing manually? I'm using Gson and LoggedInUser is the response body as I can log in when user credentials are correct – esQmo_ May 09 '20 at 16:46
  • Yes according to response because your response is the change when success and failure. – Vijendra patidar May 09 '20 at 17:19
  • The problem is he server always returns 200 this is a valid response – esQmo_ May 09 '20 at 17:21
  • Can you share your login successful response so I can easily understand this scenario? And change the response from the backend. I thin you get the every time this "statut". – Vijendra patidar May 09 '20 at 17:24
  • Updated my question with the requested infos. – esQmo_ May 09 '20 at 17:56
  • You can check from the statut if you get the success then parse data like you want, and if get ko then show the message. Follow the link which I have sent to you – Vijendra patidar May 09 '20 at 18:55
  • Well, I'll try to look at it – esQmo_ May 09 '20 at 19:01

1 Answers1

1

Check this answer it will help you.

  @POST("end_path")
      Call<ResponseBody> LoginCall(
        @Field("email") String user_id,
        @Part("paassword") String language
      );

     Call<ResponseBody> call = Constant.service.LoginCall(
                "email", "pass");
        call.enqueue(new retrofit2.Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, 
               Response<ResponseBody> response) {
                if (response.isSuccessful()) {
                    try {
                        String responseData = response.body().string();
                        JSONObject object = new JSONObject(responseData);

                   if(object.getString("statut").equalsIgnoreCase("success")){
                            LoggedInUser successData = new 
                            Gson().fromJson(responseData, LoggedInUser.class);
                            }else{
                   showToast("Email password incorrect");//or show you want 
                       this message.
                                }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (JsonSyntaxException e) {
                        e.printStackTrace();
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                } else {
                    showToast("something_went_wrong");
                }
            }
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                t.printStackTrace();
            }
        });
Vijendra patidar
  • 1,444
  • 1
  • 14
  • 24
  • 1
    This may be a correct answer, but it’d be useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who may not be familiar with the syntax. Further, it can help reduce the need for follow-up questions. Would you mind updating your comment with additional details? – Jeremy Caney May 10 '20 at 03:15