]> git.ktnx.net Git - mobile-ledger.git/commitdiff
detect and report API errors when saving new transactions
authorDamyan Ivanov <dam+mobileledger@ktnx.net>
Mon, 28 Dec 2020 11:24:58 +0000 (13:24 +0200)
committerDamyan Ivanov <dam+mobileledger@ktnx.net>
Mon, 28 Dec 2020 15:52:19 +0000 (15:52 +0000)
app/src/main/java/net/ktnx/mobileledger/async/SendTransactionTask.java
app/src/main/java/net/ktnx/mobileledger/json/ApiNotSupportedException.java
app/src/main/java/net/ktnx/mobileledger/model/MobileLedgerProfile.java
app/src/main/java/net/ktnx/mobileledger/ui/activity/MainActivity.java
app/src/main/java/net/ktnx/mobileledger/ui/activity/NewTransactionFragment.java
app/src/main/res/values-bg/strings.xml
app/src/main/res/values/strings.xml

index 14d41f9f14a9bffeef548d94b264db5382628b20..dbe4bc88647d87b129315d3d3edaff076028ba37 100644 (file)
@@ -21,6 +21,7 @@ import android.os.AsyncTask;
 import android.util.Log;
 
 import net.ktnx.mobileledger.json.API;
+import net.ktnx.mobileledger.json.ApiNotSupportedException;
 import net.ktnx.mobileledger.json.Gateway;
 import net.ktnx.mobileledger.model.LedgerTransaction;
 import net.ktnx.mobileledger.model.LedgerTransactionAccount;
@@ -73,7 +74,7 @@ public class SendTransactionTask extends AsyncTask<LedgerTransaction, Void, Void
         mProfile = profile;
         simulate = false;
     }
-    private boolean sendOK(API apiVersion) throws IOException {
+    private void sendOK(API apiVersion) throws IOException, ApiNotSupportedException {
         HttpURLConnection http = NetworkUtil.prepareConnection(mProfile, "add");
         http.setRequestMethod("PUT");
         http.setRequestProperty("Content-Type", "application/json");
@@ -82,9 +83,11 @@ public class SendTransactionTask extends AsyncTask<LedgerTransaction, Void, Void
         Gateway gateway = Gateway.forApiVersion(apiVersion);
         String body = gateway.transactionSaveRequest(transaction);
 
-        return sendRequest(http, body);
+        Logger.debug("network", "Sending using API " + apiVersion);
+        sendRequest(http, body);
     }
-    private boolean sendRequest(HttpURLConnection http, String body) throws IOException {
+    private void sendRequest(HttpURLConnection http, String body)
+            throws IOException, ApiNotSupportedException {
         if (simulate) {
             debug("network", "The request would be: " + body);
             try {
@@ -96,7 +99,7 @@ public class SendTransactionTask extends AsyncTask<LedgerTransaction, Void, Void
                 Logger.debug("network", ex.toString());
             }
 
-            return true;
+            return;
         }
 
         byte[] bodyBytes = body.getBytes(StandardCharsets.UTF_8);
@@ -124,16 +127,21 @@ public class SendTransactionTask extends AsyncTask<LedgerTransaction, Void, Void
                     case 400:
                     case 405: {
                         BufferedReader reader = new BufferedReader(new InputStreamReader(resp));
-                        String line;
+                        StringBuilder errorLines = new StringBuilder();
                         int count = 0;
                         while (count <= 5) {
-                            line = reader.readLine();
+                            String line = reader.readLine();
                             if (line == null)
                                 break;
                             Logger.debug("network", line);
+
+                            if (errorLines.length() != 0)
+                                errorLines.append("\n");
+
+                            errorLines.append(line);
                             count++;
                         }
-                        return false; // will cause a retry with another method
+                        throw new ApiNotSupportedException(errorLines.toString());
                     }
                     default:
                         BufferedReader reader = new BufferedReader(new InputStreamReader(resp));
@@ -144,8 +152,6 @@ public class SendTransactionTask extends AsyncTask<LedgerTransaction, Void, Void
                 }
             }
         }
-
-        return true;
     }
     private boolean legacySendOK() throws IOException {
         HttpURLConnection http = NetworkUtil.prepareConnection(mProfile, "add");
@@ -253,13 +259,18 @@ public class SendTransactionTask extends AsyncTask<LedgerTransaction, Void, Void
                     boolean sendOK = false;
                     for (API ver : API.allVersions) {
                         Logger.debug("network", "Trying version " + ver);
-                        if (sendOK(ver)) {
+                        try {
+                            sendOK(ver);
                             sendOK = true;
                             Logger.debug("network", "Version " + ver + " request succeeded");
 
                             break;
                         }
+                        catch (ApiNotSupportedException e) {
+                            Logger.debug("network", "Version " + ver + " seems not supported");
+                        }
                     }
+
                     if (!sendOK) {
                         Logger.debug("network", "Trying HTML form emulation");
                         legacySendOkWithRetry();
@@ -277,7 +288,7 @@ public class SendTransactionTask extends AsyncTask<LedgerTransaction, Void, Void
                     throw new IllegalStateException("Unexpected API version: " + profileApiVersion);
             }
         }
-        catch (Exception e) {
+        catch (ApiNotSupportedException | Exception e) {
             e.printStackTrace();
             error = e.getMessage();
         }
index d552a6844e990ff8e63e970b45526b6cbb0925d5..7bf84514544d4231a6632cc6b86ff1395f7bf262 100644 (file)
 
 package net.ktnx.mobileledger.json;
 
-public class ApiNotSupportedException extends Throwable {}
+import androidx.annotation.Nullable;
+
+public class ApiNotSupportedException extends Throwable {
+    public ApiNotSupportedException() {
+    }
+    public ApiNotSupportedException(@Nullable String message) {
+        super(message);
+    }
+    public ApiNotSupportedException(@Nullable String message, @Nullable Throwable cause) {
+        super(message, cause);
+    }
+    public ApiNotSupportedException(@Nullable Throwable cause) {
+        super(cause);
+    }
+    public ApiNotSupportedException(@Nullable String message, @Nullable Throwable cause,
+                                    boolean enableSuppression, boolean writableStackTrace) {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+}
index a3157cd83c9b9418aaf850a6fa4061a55e87b6a3..21d15d162ebb1743586bdb71c5f1b210e905d16f 100644 (file)
 
 package net.ktnx.mobileledger.model;
 
+import android.content.Context;
+import android.content.Intent;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
+import android.os.Bundle;
 import android.text.TextUtils;
 import android.util.SparseArray;
 
@@ -29,6 +32,8 @@ import net.ktnx.mobileledger.App;
 import net.ktnx.mobileledger.R;
 import net.ktnx.mobileledger.async.DbOpQueue;
 import net.ktnx.mobileledger.json.API;
+import net.ktnx.mobileledger.ui.activity.ProfileDetailActivity;
+import net.ktnx.mobileledger.ui.profiles.ProfileDetailFragment;
 import net.ktnx.mobileledger.utils.Logger;
 import net.ktnx.mobileledger.utils.Misc;
 import net.ktnx.mobileledger.utils.SimpleDate;
@@ -161,6 +166,17 @@ public final class MobileLedgerProfile {
             db.endTransaction();
         }
     }
+    static public void startEditProfileActivity(Context context, MobileLedgerProfile profile) {
+        Intent intent = new Intent(context, ProfileDetailActivity.class);
+        Bundle args = new Bundle();
+        if (profile != null) {
+            int index = Data.getProfileIndex(profile);
+            if (index != -1)
+                intent.putExtra(ProfileDetailFragment.ARG_ITEM_ID, index);
+        }
+        intent.putExtras(args);
+        context.startActivity(intent, args);
+    }
     public HledgerVersion getDetectedVersion() {
         return detectedVersion;
     }
index 9cb68cb85a49d146a37e538bfa0fc5cb171edfe5..370c5e2b6e95ab905dd80804df7c3ae238a56b36 100644 (file)
@@ -57,7 +57,6 @@ import net.ktnx.mobileledger.model.Data;
 import net.ktnx.mobileledger.model.MobileLedgerProfile;
 import net.ktnx.mobileledger.ui.MainModel;
 import net.ktnx.mobileledger.ui.account_summary.AccountSummaryFragment;
-import net.ktnx.mobileledger.ui.profiles.ProfileDetailFragment;
 import net.ktnx.mobileledger.ui.profiles.ProfilesRecyclerViewAdapter;
 import net.ktnx.mobileledger.ui.transaction_list.TransactionListFragment;
 import net.ktnx.mobileledger.utils.Colors;
@@ -231,12 +230,12 @@ public class MainActivity extends ProfileThemedActivity {
         }
 
         findViewById(R.id.btn_no_profiles_add).setOnClickListener(
-                v -> startEditProfileActivity(null));
+                v -> MobileLedgerProfile.startEditProfileActivity(this, null));
 
         findViewById(R.id.btn_add_transaction).setOnClickListener(this::fabNewTransactionClicked);
 
         findViewById(R.id.nav_new_profile_button).setOnClickListener(
-                v -> startEditProfileActivity(null));
+                v -> MobileLedgerProfile.startEditProfileActivity(this, null));
 
         findViewById(R.id.transaction_list_cancel_download).setOnClickListener(
                 this::onStopTransactionRefreshClick);
@@ -471,17 +470,6 @@ public class MainActivity extends ProfileThemedActivity {
 
         recreate();
     }
-    public void startEditProfileActivity(MobileLedgerProfile profile) {
-        Intent intent = new Intent(this, ProfileDetailActivity.class);
-        Bundle args = new Bundle();
-        if (profile != null) {
-            int index = Data.getProfileIndex(profile);
-            if (index != -1)
-                intent.putExtra(ProfileDetailFragment.ARG_ITEM_ID, index);
-        }
-        intent.putExtras(args);
-        startActivity(intent, args);
-    }
     public void fabNewTransactionClicked(View view) {
         Intent intent = new Intent(this, NewTransactionActivity.class);
         startActivity(intent);
@@ -630,7 +618,7 @@ public class MainActivity extends ProfileThemedActivity {
                 builder.setMessage(error);
                 builder.setPositiveButton(R.string.btn_profile_options, (dialog, which) -> {
                     Logger.debug("error", "will start profile editor");
-                    startEditProfileActivity(profile);
+                    MobileLedgerProfile.startEditProfileActivity(this, profile);
                 });
                 builder.create()
                        .show();
index e705d1c102df4a01348d77b57ac118806e4fc13d..d8271db448c65531f04d830dcbd892cbbe7cb413 100644 (file)
@@ -18,6 +18,7 @@
 package net.ktnx.mobileledger.ui.activity;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.os.Bundle;
 import android.renderscript.RSInvalidStateException;
 import android.view.LayoutInflater;
@@ -30,6 +31,7 @@ import android.widget.ProgressBar;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
 import androidx.lifecycle.ViewModelProvider;
@@ -40,6 +42,7 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
 import com.google.android.material.snackbar.Snackbar;
 
 import net.ktnx.mobileledger.R;
+import net.ktnx.mobileledger.json.API;
 import net.ktnx.mobileledger.model.Data;
 import net.ktnx.mobileledger.model.LedgerTransaction;
 import net.ktnx.mobileledger.model.LedgerTransactionAccount;
@@ -152,8 +155,34 @@ public class NewTransactionFragment extends Fragment {
             String error = args.getString("error");
             if (error != null) {
                 Logger.debug("new-trans-f", String.format("Got error: %s", error));
-                Snackbar.make(list, error, Snackbar.LENGTH_LONG)
-                        .show();
+
+                Context context = getContext();
+                if (context != null) {
+                    AlertDialog.Builder builder = new AlertDialog.Builder(context);
+                    final Resources resources = context.getResources();
+                    final StringBuilder message = new StringBuilder();
+                    message.append(resources.getString(R.string.err_json_send_error_head));
+                    message.append("\n\n");
+                    message.append(error);
+                    if (mProfile.getApiVersion()
+                                .equals(API.auto))
+                        message.append(
+                                resources.getString(R.string.err_json_send_error_unsupported));
+                    else {
+                        message.append(resources.getString(R.string.err_json_send_error_tail));
+                        builder.setPositiveButton(R.string.btn_profile_options, (dialog, which) -> {
+                            Logger.debug("error", "will start profile editor");
+                            MobileLedgerProfile.startEditProfileActivity(context, mProfile);
+                        });
+                    }
+                    builder.setMessage(message);
+                    builder.create()
+                           .show();
+                }
+                else {
+                    Snackbar.make(list, error, Snackbar.LENGTH_LONG)
+                            .show();
+                }
                 keep = true;
             }
         }
index dbdbb99180d3896a3ce82f249beb9eadc1d2a6ed..d52c59cee0a9eabb8c575c28cb6dc533ce16842d 100644 (file)
     <string name="new_transaction_fab_description">Знак плюс</string>
     <string name="api_1_19_1">Версия 1.19.1</string>
     <string name="profile_server_version_title">Версия на сървъра</string>
-    <string name="err_json_parser_error">Ð\93Ñ\80еÑ\88ка Ð¿Ñ\80и Ñ\80азÑ\87иÑ\82ане Ð½Ð° Ð¾Ñ\82говоÑ\80а Ð¾Ñ\82 Ñ\81Ñ\8aÑ\80вÑ\8aÑ\80а. Ð\92еÑ\80оÑ\8fÑ\82но Ð½Ð°Ñ\81Ñ\82Ñ\80оенаÑ\82а Ð²Ñ\80Ñ\81иÑ\8f Ð½Ð° Ð¿Ñ\80оÑ\82окола Ðµ Ð³Ñ\80еÑ\88на.</string>
+    <string name="err_json_parser_error">Ð\93Ñ\80еÑ\88ка Ð¿Ñ\80и Ñ\80азÑ\87иÑ\82ане Ð½Ð° Ð¾Ñ\82говоÑ\80а Ð¾Ñ\82 Ñ\81Ñ\8aÑ\80вÑ\8aÑ\80а. Ð\92еÑ\80оÑ\8fÑ\82но Ð½Ð°Ñ\81Ñ\82Ñ\80оенаÑ\82а Ð²Ñ\80Ñ\81иÑ\8f Ð½Ð° Ð¿Ñ\80оÑ\82окола Ð½Ðµ Ñ\81е Ð¿Ð¾Ð´Ð´Ñ\8aÑ\80жа.</string>
     <string name="btn_profile_options">Настройка на профила</string>
+    <string name="err_json_send_error_head">Грешка при изпращане на движението към сървъра</string>
+    <string name="err_json_send_error_tail">Вероятно настроената версия на протокола не се поддържа.</string>
 </resources>
index ea7d15482180d3f559118e2b986baf624a32c92f..63fb70e4a84db6895df65552262b67791afff3e0 100644 (file)
     <string name="profile_server_version_title">Server version</string>
     <string name="err_json_parser_error">Error parsing packend JSON response. Perhaps the configured API version doesn\'t match</string>
     <string name="btn_profile_options">Configure profile</string>
+    <string name="err_json_send_error_head">Error storing transaction on backend server</string>
+    <string name="err_json_send_error_tail">A mismatch in the configured API version could be causing this</string>
+    <string name="err_json_send_error_unsupported">Perhaps the API of the backend server is not supported by MoLe</string>
 </resources>