Skip to content
4 changes: 1 addition & 3 deletions app/src/org/commcare/activities/InstallFromListActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
import org.commcare.core.network.AuthInfo;
import org.commcare.core.network.AuthenticationInterceptor;
import org.commcare.dalvik.R;
import org.commcare.google.services.analytics.AnalyticsParamValue;
import org.commcare.google.services.analytics.FirebaseAnalyticsUtil;
import org.commcare.models.database.SqlStorage;
import org.commcare.network.CommcareRequestGenerator;
import org.commcare.preferences.GlobalPrivilegesManager;
Expand Down Expand Up @@ -326,7 +324,7 @@ private void saveLastSuccessfulCredentials() {
}

@Override
public void processClientError(int responseCode) {
public void processClientError(int responseCode, InputStream errorStream) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why there is change in this method? I cannot see its being used further.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the same interface used by ConnectNetworkHelper

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's the same interface used by ConnectNetworkHelper

handleRequestError(responseCode, true);
}

Expand Down
2 changes: 1 addition & 1 deletion app/src/org/commcare/activities/PostRequestActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public void processSuccess(int responseCode, InputStream responseData, String ap
}

@Override
public void processClientError(int responseCode) {
public void processClientError(int responseCode, InputStream errorStream) {
String clientErrorMessage;
switch (responseCode) {
case 409:
Expand Down
2 changes: 1 addition & 1 deletion app/src/org/commcare/activities/QueryRequestActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ private boolean isResponseEmpty(ExternalDataInstance instance) {
}

@Override
public void processClientError(int responseCode) {
public void processClientError(int responseCode, InputStream errorStream) {
enterErrorState(Localization.get("post.client.error", responseCode + ""));
}

Expand Down
10 changes: 5 additions & 5 deletions app/src/org/commcare/connect/MessageManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public void processSuccess(int responseCode, InputStream responseData) {
}

@Override
public void processFailure(int responseCode, @Nullable InputStream errorResponse, String url) {
public void processFailure(int responseCode, String url, String errorBody) {
listener.connectActivityComplete(false);
}

Expand Down Expand Up @@ -139,7 +139,7 @@ public void processSuccess(int responseCode, InputStream responseData) {

@Override

public void processFailure(int responseCode, @Nullable InputStream errorResponse, String url) {
public void processFailure(int responseCode, String url, String errorBody) {
listener.connectActivityComplete(false);
}

Expand Down Expand Up @@ -191,7 +191,7 @@ public void processSuccess(int responseCode, InputStream responseData) {
}

@Override
public void processFailure(int responseCode, @Nullable InputStream errorResponse, String url) {
public void processFailure(int responseCode, String url, String errorBody) {
if (listener != null) {
listener.connectActivityComplete(false);
}
Expand Down Expand Up @@ -251,7 +251,7 @@ public void processSuccess(int responseCode, InputStream responseData) {
}

@Override
public void processFailure(int responseCode, @Nullable InputStream errorResponse, String url) {
public void processFailure(int responseCode, String url, String errorBody) {
listener.connectActivityComplete(false);
}

Expand Down Expand Up @@ -305,7 +305,7 @@ public void processSuccess(int responseCode, InputStream responseData) {
}

@Override
public void processFailure(int responseCode, @Nullable InputStream errorResponse, String url) {
public void processFailure(int responseCode, String url, String errorBody) {
listener.connectActivityComplete(false);
}

Expand Down
14 changes: 9 additions & 5 deletions app/src/org/commcare/connect/network/ConnectNetworkHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.commcare.tasks.templates.CommCareTask;
import org.commcare.utils.CrashUtil;
import org.commcare.utils.GlobalErrors;
import org.javarosa.core.io.StreamsUtil;
import org.javarosa.core.services.Logger;

import java.io.IOException;
Expand All @@ -31,6 +32,7 @@
import java.util.Locale;
import java.util.Map;

import kotlin.Pair;
import kotlin.jvm.Volatile;
import okhttp3.MediaType;
import okhttp3.RequestBody;
Expand Down Expand Up @@ -324,7 +326,7 @@ public void processSuccess(int responseCode, InputStream responseData, String ap
}

@Override
public void processClientError(int responseCode) {
public void processClientError(int responseCode, InputStream errorStream) {
onFinishProcessing(context, background);

String message = String.format(Locale.getDefault(), "Call:%s\nResponse code:%d", url, responseCode);
Expand All @@ -340,7 +342,9 @@ public void processClientError(int responseCode) {
ConnectSsoHelper.discardTokens(context, null);
handler.processTokenUnavailableError();
} else {
handler.processFailure(responseCode, null, url);
String errorBody = NetworkUtils.getErrorBody(errorStream);
NetworkUtils.logFailedResponse("", responseCode, url, errorBody);
handler.processFailure(responseCode, url, errorBody);
}
}
}
Expand All @@ -353,7 +357,7 @@ public void processServerError(int responseCode) {
CrashUtil.reportException(new Exception(message));

//500 error for internal server error
handler.processFailure(responseCode, null, url);
handler.processFailure(responseCode, url, "");
}

@Override
Expand All @@ -363,7 +367,7 @@ public void processOther(int responseCode) {
String message = String.format(Locale.getDefault(), "Call:%s\nResponse code:%d", url, responseCode);
CrashUtil.reportException(new Exception(message));

handler.processFailure(responseCode, null, url);
handler.processFailure(responseCode, url, "");
}

@Override
Expand All @@ -373,7 +377,7 @@ public void handleIOException(IOException exception) {
handler.processNetworkFailure();
} else {
Logger.exception("IO Exception during API call", exception);
handler.processFailure(-1, null, url);
handler.processFailure(-1, url, "");
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/src/org/commcare/connect/network/IApiCallback.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
public interface IApiCallback {
void processSuccess(int responseCode, InputStream responseData);
void processFailure(int responseCode, @Nullable InputStream errorResponse, String url);
void processFailure(int responseCode, String url, String errorBody);
void processNetworkFailure();
void processOldApiError();
void processTokenUnavailableError();
Expand Down
92 changes: 92 additions & 0 deletions app/src/org/commcare/connect/network/NetworkUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package org.commcare.connect.network

import org.commcare.util.LogTypes
import org.javarosa.core.io.StreamsUtil
import org.javarosa.core.services.Logger
import org.json.JSONObject
import retrofit2.HttpException
import retrofit2.Response
import java.io.IOException
import java.io.InputStream
import java.nio.charset.StandardCharsets

object NetworkUtils {

@JvmStatic
fun getErrorBody(stream: InputStream?): String {
try {
if (stream != null) {
val errorBytes = StreamsUtil.inputStreamToByteArray(stream)
return String(errorBytes, StandardCharsets.UTF_8)
}
} catch (e: Exception) {
Logger.exception("Error parsing error_code", e);
}
return ""
}

/**
* Extracts error_code and error_sub_code from a JSON error response body.
* If the stream is null or parsing fails, returns empty strings for both codes.
*
* @param stream InputStream of the error response body
* @return Pair of error_code and error_sub_code
*/
@JvmStatic
fun getErrorCodes(errorBody: String): Pair<String, String> {
var errorCode = ""
var errorSubCode = ""
try {
val json = JSONObject(errorBody)
errorCode = json.optString("error_code", "");
errorSubCode = json.optString("error_sub_code", "");
} catch (e: Exception) {
Logger.exception("Error parsing error_code", e);
}
return Pair(errorCode, errorSubCode)
}

@JvmStatic
fun logFailedResponse(
responseMessage: String,
responseCode: Int,
endPoint: String,
errorBody: String
) {
var message = "Response Message: $responseMessage | Response Code: $responseCode"
message += if (errorBody.isNotEmpty()) " | error: $errorBody" else ""
var errorMessage = when (responseCode) {
400 -> "Bad Request: $message"
401 -> "Unauthorized: $message"
404 -> "Not Found: $message"
500 -> "Server Error: $message"
else -> "API Error: $message"

}
errorMessage += " for url ${endPoint ?: "unknown url"}"

Logger.log(
LogTypes.TYPE_ERROR_SERVER_COMMS,
errorMessage
)
Logger.exception(LogTypes.TYPE_ERROR_SERVER_COMMS, Throwable(errorMessage))
}

@JvmStatic
fun logNetworkError(t: Throwable, endPoint: String) {
val message = t.message

var errorMessage = when (t) {
is IOException -> "Network Error: $message"
is HttpException -> "HTTP Error: $message"
else -> "Unexpected Error: $message"
}

errorMessage += " for url ${endPoint ?: "url not found"}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shubham1g5 Can we make it unknown url as url not found seems like 404 error

Logger.log(
LogTypes.TYPE_ERROR_SERVER_COMMS,
errorMessage
)
Logger.exception(errorMessage, t)
}
}
61 changes: 15 additions & 46 deletions app/src/org/commcare/connect/network/base/BaseApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import okhttp3.ResponseBody
import org.commcare.activities.CommCareActivity
import org.commcare.connect.ConnectConstants
import org.commcare.connect.network.IApiCallback
import org.commcare.util.LogTypes
import org.commcare.connect.network.NetworkUtils
import org.commcare.connect.network.NetworkUtils.getErrorCodes
import org.commcare.connect.network.NetworkUtils.logFailedResponse
import org.commcare.connect.network.NetworkUtils.logNetworkError
import org.javarosa.core.io.StreamsUtil
import org.javarosa.core.services.Logger
import retrofit2.Call
import retrofit2.Callback
import retrofit2.HttpException
import retrofit2.Response
import java.io.IOException

Expand All @@ -37,15 +40,20 @@ class BaseApi {
callback.processSuccess(response.code(), responseStream)
}
} catch (e: IOException) {
Logger.exception("Error reading response stream", e);
// Handle error when reading the stream
callback.processFailure(response.code(), null, endPoint)
callback.processFailure(response.code(), endPoint, "")
}
} else {
// Handle validation errors
logFailedResponse(response, endPoint)
val stream = if (response.errorBody() != null) response.errorBody()!!
.byteStream() else null
callback.processFailure(response.code(), stream, endPoint)
try {
val errorBody = NetworkUtils.getErrorBody(stream)
logFailedResponse(response.message(), response.code(), endPoint, errorBody)
callback.processFailure(response.code(), endPoint, errorBody)
} finally {
StreamsUtil.closeStream(stream)
}
}
}

Expand Down Expand Up @@ -76,45 +84,6 @@ class BaseApi {
}
}
}


fun logFailedResponse(response: Response<*>, endPoint: String) {
val message = response.message()
var errorMessage = when (response.code()) {
400 -> "Bad Request: $message"
401 -> "Unauthorized: $message"
404 -> "Not Found: $message"
500 -> "Server Error: $message"
else -> "API Error: $message"

}
errorMessage += " for url ${endPoint ?: "url not found"}"

Logger.log(
LogTypes.TYPE_ERROR_SERVER_COMMS,
errorMessage
)
Logger.exception(LogTypes.TYPE_ERROR_SERVER_COMMS, Throwable(errorMessage))
}


fun logNetworkError(t: Throwable, endPoint: String) {
val message = t.message

var errorMessage = when (t) {
is IOException -> "Network Error: $message"
is HttpException -> "HTTP Error: $message"
else -> "Unexpected Error: $message"
}

errorMessage += " for url ${endPoint ?: "url not found"}"
Logger.log(
LogTypes.TYPE_ERROR_SERVER_COMMS,
errorMessage
)
Logger.exception(errorMessage, t)
}

}

}
}
4 changes: 2 additions & 2 deletions app/src/org/commcare/connect/network/base/BaseApiCallback.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import java.io.InputStream
abstract class BaseApiCallback<T>(val baseApiHandler: BaseApiHandler<T>) :

IApiCallback {
override fun processFailure(responseCode: Int, errorResponse: InputStream?, url: String?) {
override fun processFailure(responseCode: Int, url: String?, errorBody: String) {
// Common error_code handler used before checking error response code
when (responseCode) {
401 -> baseApiHandler.onFailure(
Expand Down Expand Up @@ -79,4 +79,4 @@ abstract class BaseApiCallback<T>(val baseApiHandler: BaseApiHandler<T>) :
null
)
}
}
}
Loading