okhttp get failure response - android

I've implemented okhttp in my android client for network calls.
When i get a failure response i get the failure code and the text related to the code as a message but i don't get the custom failure response that the server sends me.
In my failure response in the implemented code the message i get is just "Bad Request".
Whereas the same response from the browser is as follows.
How do i get the error message the server is giving me back?
My code
private void executeCall(Request request, final ResponseListener listener) {
mOKHttpClient.newCall(request)
.enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
postFailure(listener, (String) call.request()
.tag(),e.toString());
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
if(response.isSuccessful()) {
String responseString = response.body().string();
postSuccess(listener, (String)call.request().tag(), responseString);
}
else {
postFailure(listener, (String)call.request().tag(),response.code()+","+response.message());
}
}
});
}
Here's my response in case of failure.

You will have to catch error response by body() because response.message() returns HTTP status message.
In the screen shot provided by you:
Status is broken down in OkHttp like response.code() for HTTP status code which is 400 in your case and response.message() for HTTP status message which is Bad Request in your case.
The body of the response (be it success or failure) is response.body(). And if you want to get it as a String, then call response.body().string().
#Override
public void onResponse(Call call, final Response response) throws IOException {
if(response.isSuccessful()) {
String responseString = response.body().string();
postSuccess(listener, (String)call.request().tag(), responseString);
}
else {
String errorBodyString = response.body().string();
postFailure(listener, (String)call.request().tag(),response.code()+","+errorBodyString);
}
}
As per comments:
Since you want to read Message object from the response, try to do like this:
JSONObject object = new JSONObject (response.body().string());
String messageString = object.getString("Message");

if you are trying to get (okhttp3.ResponseBody) errorResponse from Retrofit response do this..
// Retrofit onResponseCall
#Override
public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
if (response.errorBody() != null) {
try {
Log.e("errorResponse","" + response.errorBody().toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}

Related

how to fetch response from retrofit JSON without key

In my retrofit JSON response there is a single value without any key and type.In my JSON i have passed three-element as per need and now i get a response as shown below. so how can I fetch that response?
My JSON of Response looks like -
successful
This is my JSON code-
private void ASSIGN_DATA() {
ApiInterface apiInterface=ApiClient.getClient().create(ApiInterface.class);
Call<ArrayList<price_get_set>> call=apiInterface.assignItemToJson(select_date.getText().toString(),
id,item_list);
call.enqueue(new Callback<ArrayList<price_get_set>>() {
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onResponse(Call<ArrayList<price_get_set>> call, Response<ArrayList<price_get_set>> response) {
progress.dismiss();
Log.d("URL::",response.toString());
Log.d("new URL::",response.body().toString());
try {
if (response.isSuccessful()) {
Toast.makeText(Items_List.this, "Successs", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Items_List.this, Item_Accept_Reject_List.class);
startActivity(intent);
}
else
Toast.makeText(Items_List.this, "Something went Wrong", Toast.LENGTH_SHORT).show();
}
catch (Exception ex){
Log.e("ERROR::",ex.getMessage());
}
}
#Override
public void onFailure(Call<ArrayList<price_get_set>> call, Throwable t) {
progress.dismiss();
Log.i("FAILURE ERROR::",t.getMessage());
}
});
}
You can use response.body().string().
It will convert your response in String.
Example On Your onResponse method of API you have to use this code.
#Override
public void onResponse(Response<ResponseBody> response) {
try {
String responseString = response.body().toString();//This a response as string
Log.d("Response : " + responseString);
} catch (IOException e) {
e.printStackTrace();
}
}

Fetch a Single Key Value pair from my Retrofit response

I am getting a response from the GET method in the form of
{data : { "type " : User ........ "attribute" : { "isemailverified" : false.....}....}
I want to fetch the value of isemailverified
I am using Retrofit to fetch data
useCaseFactory.getUserDomainModel().GetUser(userId, withDataArray, null, new Callback() {
#Override
public void onFailure(Call call, IOException e) {
System.out.println("ERROR: " + e.getMessage());
}
#Override
public void onResponse(Call call, Response response) throws IOException {
ResponseBody responseBody = response.body();
System.out.println(response.body().string());
}

Gson Retrofit Json API returns Webpage on Error

I am using an API the returns a Json object { "results": 1, "data": [...]} on success and a webpage "<DOCTYPE HTML> <HTML>.... </HTML>" on error. How can I handle this? I am using Retrofit 2 and Gson on Android in Java. I am also using two custom deserializers to handle string returned instead of object when a data item errors out.
Have you tried to use the OkHttp3 ResponseBody for your call, and based on the type of the response either parse the Json with Gson or display an error ?
For instance you can create a function that determines if a string is a gson like this:
public static boolean isJson(String Json) {
Gson gson = new Gson();
try {
gson.fromJson(Json, Object.class);
return true;
} catch (com.google.gson.JsonSyntaxException ex) {
return false;
}
}
Then do your retrofit call like this:
Call<ResponseBody> res = yourService.yourmethod();
res.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
try {
String resString = response.body().string();
if (isJson(resString)) {
Gson gson = new Gson();
YourModel responseObject = gson.fromJson(resString, YourModel.class);
// do something with the object
} else { // this is not a Json so most likely your html response
// Do something else, like display an error
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
If you need to parse the html to display what is returned, you can also use Jsoup, here it would be something like Document document = Jsoup.parse(resString);, then do what you need with the result.
You also have the option of using a WebView and directly display the html response in it, with webView.loadData(resString, "text/html", "UTF-8");
According to the response code, you can handle it but it should take care by your backend. Backend developer should give proper error message along with response code.
in case the API returns something else than HTTP 200 OK on error, one can differ:
#Override
public void onResponse(#NonNull Call<SomeModel> call, #NonNull Response<SomeModel> response) {
switch(response.code()) {
case 200: {
if (response.body() != null) {
...
}
break;
}
default: {
if (response.errorBody() != null) {
String content = response.errorBody().string();
...
}
break;
}
}
}

How to get response body in okhttp when code is 401?

I am using OkHttp 3.2.0 and here is code for building request object:
MediaType JSON = MediaType.parse(AppConstants.CONTENT_TYPE_VALUE_JSON);
RequestBody body = RequestBody.create(JSON, requestBody);
HttpUrl url = new HttpUrl.Builder()
.scheme("http")
.host("192.168.0.104")
.port(8080)
.addPathSegment("mutterfly-server")
.addPathSegment("j_spring_security_check")
.addQueryParameter("j_username", jsonObject.getString("emailId"))
.addQueryParameter("j_password", jsonObject.getString("password"))
.build();
request = new Request.Builder()
.addHeader(AppConstants.CONTENT_TYPE_LABEL, AppConstants.CONTENT_TYPE_VALUE_JSON)
.addHeader(AppConstants.ACCEPT_LABEL, AppConstants.CONTENT_TYPE_VALUE_JSON)
.url(url)
.post(body)
.build();
And here is how I parse the response:
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
String respBody;
if (response.isSuccessful()) {
if (response.body() != null) {
respBody = response.body().string();
Log.i(TAG, respBody);
response.body().close();
if (AppMethods.checkIfNull(loginParserListener)) {
try {
final VUser user = AppMethods.getGsonInstance().fromJson(respBody, VUser.class);
} catch (Exception e) {
}
}
}
} else {
switch (response.code()){
case 401:
String body="HTTP_UNAUTHORIZED";
break;
}
}
}
});
This is the ideal response(from web rest client) when authentication is failed.
{"msgDesc":"The username or password you entered is incorrect..","statusCode":401}
EDIT:
response.toString() returns
Response{protocol=http/1.1, code=401, message=Unauthorized, url=http://192.168.0.104:8080/mutterfly-server/j_spring_security_check?j_username=s#s.s&j_password=1}
response.body().toString() returns
okhttp3.internal.http.RealResponseBody#528ae030
I want to fetch the msgDesc which is in response body. Is there any method which will return this string?
Try this:
switch (response.code()){
case 401:
JsonObject object=new JsonObject(response.body().string());
String body=object.getString("msgDesc");
break;
}
It's quite weird but Square, the company behind OkHttp, has chosen to not use 'toString()' but 'string()' as method for getting the body as a String.
So this works;
String string = response.body().string();
//convert to JSON and get your value
But this doesn't:
String string = response.body().toString();
401 means permission denied.
Check if your token is valid or user/password is correct.

Retrofit - POST request with #Path and without parameters

The request to API as follows:
POST /verify/phone/{userid}/
Mandatory parameters: userid (integer)
Return: nothing
I receive Bad Request error all the time if I want to verify user with id 1 (for example):
Response{protocol=http/1.1, code=400, message=Bad Request, url=http://dummyapi.com/verify/phone/1/}
Posting the same request using Postman works well.
Code:
#POST("/verify/phone/{userid}/")
Call<String> postVerifyPhone(#Path("userid") int userId);
public void postVerifyPhone(int userID){
showProgressBar();
RestClient.GitApiInterface service = RestClient.getClient();
Call<String> call = service.postVerifyPhone(userID);
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Response<String> response) {
hideProgressBar();
if (response.isSuccess()) {
String result = response.body();
} else {
Log.d("Fail: ", response.body()); //everytime here with Bad Request
}
}
#Override
public void onFailure(Throwable t) {
hideProgressBar();
}
});
}
I'm using String as the return type since there's message returned when there're no user with requested ID in db.
What could be a cause?
I am calling below code for reading response data.
public void postVerifyPhone(int userID){
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(Constants.URL).build();
RetrofitApi retrofitApi = restAdapter.create(RetrofitApi.class);
retrofitApi.postVerifyPhone(userID, new Callback<Response>() {
#Override
public void success(Response response, Response response2) {
BufferedReader reader = null;
StringBuilder sb = new StringBuilder();
try {
reader = new BufferedReader(new InputStreamReader(response.getBody().in()));
String line;
try {
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
String result = sb.toString();
// System.out.println("res:" + result.toString());
}
#Override
public void failure(RetrofitError error) {
hidePDialog();
}
});
}
below is postVerifyPhone() code
#FormUrlEncoded
#POST("/verify/phone/")
public void postVerifyPhone(#Field("userID") String userID, Callback<Response> resonse);
It is working fine for me.please check it once.
I think the right annotation is #PathParam, not #Path

Categories

Resources