From 636b6466a983df39bf14a9a319dcdb4a930d2e7f Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Fri, 24 Oct 2025 07:44:07 +0300 Subject: [PATCH 1/2] Fixed cyclic failure in Preferences and logging This exception caused a cycle as the Logger depends on Preferences. See: https://www.reddit.com/r/cn1/comments/1oe6fvq/error_on_preferences/ --- CodenameOne/src/com/codename1/io/Preferences.java | 4 ++-- CodenameOne/src/com/codename1/io/Storage.java | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CodenameOne/src/com/codename1/io/Preferences.java b/CodenameOne/src/com/codename1/io/Preferences.java index 0645884840..d7c6c4c985 100644 --- a/CodenameOne/src/com/codename1/io/Preferences.java +++ b/CodenameOne/src/com/codename1/io/Preferences.java @@ -82,7 +82,7 @@ public static void setPreferencesLocation(String storageFileName) { private synchronized static Hashtable get() { if (p == null) { if (Storage.getInstance().exists(preferencesLocation)) { - p = (Hashtable) Storage.getInstance().readObject(preferencesLocation); + p = (Hashtable) Storage.getInstance().readObject(preferencesLocation, false); } if (p == null) { p = new Hashtable(); @@ -92,7 +92,7 @@ private synchronized static Hashtable get() { } private static synchronized void save() { - Storage.getInstance().writeObject(preferencesLocation, p); + Storage.getInstance().writeObject(preferencesLocation, p, false); } /** diff --git a/CodenameOne/src/com/codename1/io/Storage.java b/CodenameOne/src/com/codename1/io/Storage.java index b65e71dc63..78d4569663 100644 --- a/CodenameOne/src/com/codename1/io/Storage.java +++ b/CodenameOne/src/com/codename1/io/Storage.java @@ -233,6 +233,10 @@ public int entrySize(String name) { * @return true for success, false for failure */ public boolean writeObject(String name, Object o) { + return writeObject(name, o, true); + } + + boolean writeObject(String name, Object o, boolean sendLog) { name = fixFileName(name); cache.put(name, o); DataOutputStream d = null; @@ -243,7 +247,7 @@ public boolean writeObject(String name, Object o) { return true; } catch (Exception err) { Log.e(err); - if (Log.isCrashBound()) { + if (sendLog && Log.isCrashBound()) { Log.sendLog(); } Util.getImplementation().deleteStorageFile(name); @@ -263,6 +267,10 @@ public boolean writeObject(String name, Object o) { * @return object stored under that name */ public Object readObject(String name) { + return readObject(name, true); + } + + Object readObject(String name, boolean sendLog) { name = fixFileName(name); Object o = cache.get(name); if (o != null) { @@ -281,7 +289,7 @@ public Object readObject(String name) { } catch (Throwable err) { Log.p("Error while reading: " + name); Log.e(err); - if (Log.isCrashBound()) { + if (sendLog && Log.isCrashBound()) { Log.sendLog(); } Util.getImplementation().cleanup(d); From 664c487644e2987a56481d1acd1440a85a316856 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Fri, 24 Oct 2025 07:56:16 +0300 Subject: [PATCH 2/2] Revised based on review --- CodenameOne/src/com/codename1/io/Storage.java | 47 +++++++++++++++---- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/CodenameOne/src/com/codename1/io/Storage.java b/CodenameOne/src/com/codename1/io/Storage.java index 78d4569663..7cfe222d08 100644 --- a/CodenameOne/src/com/codename1/io/Storage.java +++ b/CodenameOne/src/com/codename1/io/Storage.java @@ -236,7 +236,21 @@ public boolean writeObject(String name, Object o) { return writeObject(name, o, true); } - boolean writeObject(String name, Object o, boolean sendLog) { + /** + *

Writes the given object to storage assuming it is an externalizable type + * or one of the supported types.

+ * + *

+ * The sample below demonstrates the usage and registration of the {@link com.codename1.io.Externalizable} interface: + *

+ * + * + * @param name store name + * @param o object to store + * @param includeLogging During app initialization, the logging on error might impact the apps stability + * @return true for success, false for failure + */ + public boolean writeObject(String name, Object o, boolean includeLogging) { name = fixFileName(name); cache.put(name, o); DataOutputStream d = null; @@ -246,9 +260,11 @@ boolean writeObject(String name, Object o, boolean sendLog) { d.close(); return true; } catch (Exception err) { - Log.e(err); - if (sendLog && Log.isCrashBound()) { - Log.sendLog(); + if(includeLogging) { + Log.e(err); + if (Log.isCrashBound()) { + Log.sendLog(); + } } Util.getImplementation().deleteStorageFile(name); Util.getImplementation().cleanup(d); @@ -270,7 +286,18 @@ public Object readObject(String name) { return readObject(name, true); } - Object readObject(String name, boolean sendLog) { + /** + *

Reads the object from the storage, returns null if the object isn't there

+ *

+ * The sample below demonstrates the usage and registration of the {@link com.codename1.io.Externalizable} interface: + *

+ * + * + * @param name name of the store + * @param includeLogging During app initialization, the logging on error might impact the apps stability + * @return object stored under that name + */ + public Object readObject(String name, boolean includeLogging) { name = fixFileName(name); Object o = cache.get(name); if (o != null) { @@ -287,10 +314,12 @@ Object readObject(String name, boolean sendLog) { cache.put(name, o); return o; } catch (Throwable err) { - Log.p("Error while reading: " + name); - Log.e(err); - if (sendLog && Log.isCrashBound()) { - Log.sendLog(); + if(includeLogging) { + Log.p("Error while reading: " + name); + Log.e(err); + if (Log.isCrashBound()) { + Log.sendLog(); + } } Util.getImplementation().cleanup(d); return null;