=== modified file 'src/com/goldencode/p2j/oo/core/AssertionFailedError.java'
--- src/com/goldencode/p2j/oo/core/AssertionFailedError.java	2021-02-21 16:25:50 +0000
+++ src/com/goldencode/p2j/oo/core/AssertionFailedError.java	2022-11-15 19:41:34 +0000
@@ -2,7 +2,7 @@
 ** Module   : AssertionFailedError.java
 ** Abstract : Implementation of the OpenEdge.Core.AssertionFailedError builtin class.
 **
-** Copyright (c) 2019-2021, Golden Code Development Corporation.
+** Copyright (c) 2019-2022, Golden Code Development Corporation.
 **
 ** -#- -I- --Date-- -------------------------------Description--------------------------------
 ** 001 CA  20190423 Created the first version, by converting the legacy skeleton .cls file and
@@ -12,6 +12,7 @@
 ** 003 CA  20191024 Added method support levels and updated the class support level.
 ** 004 CA  20210221 Fixed 'qualified', 'extent' and 'returns' annotations at the legacy
 **                  signature.
+** 005 VVT 2022zzzz Serialization support added (see #4658). Missing Javadocs added.
 */
 
 /*
@@ -69,15 +70,17 @@
 
 package com.goldencode.p2j.oo.core;
 
+import static com.goldencode.p2j.report.ReportConstants.*;
+import static com.goldencode.p2j.util.BlockManager.*;
+import static com.goldencode.p2j.util.TextOps.substitute;
+
+import java.io.*;
+
 import com.goldencode.p2j.util.*;
-import com.goldencode.p2j.oo.lang.*;
-
-import static com.goldencode.p2j.util.BlockManager.*;
-import static com.goldencode.p2j.report.ReportConstants.*;
-import static com.goldencode.p2j.util.InternalEntry.Type;
+import com.goldencode.p2j.util.InternalEntry.*;
 
 /**
- * Business logic (converted to Java from the 4GL source code
+ * Business logic (initially converted to Java from the 4GL source code
  * in OpenEdge/Core/AssertionFailedError.cls).
  */
 @LegacyResource(resource = "OpenEdge.Core.AssertionFailedError")
@@ -85,52 +88,218 @@
 public class AssertionFailedError
 extends com.goldencode.p2j.oo.lang.AppError
 {
-   private String _msg;
-   
+   /**
+    * The actual value if was set in the object constructor, otherwise {@code null} 
+    */
+   private BaseDataType actual;
+
+   /**
+    * The expected value if was set in the object constructor, otherwise {@code null} 
+    */
+   private BaseDataType expected;
+   
+   /**
+    * The failure message or {@code null} if no message was set.
+    */
+   private String msg;
+   
+   /**
+    * Default constructor. Instances are created using this constructor,
+    * then initialized in another call.
+    */
+   public AssertionFailedError()
+   {
+      // no-op
+   }
+
+   /**
+    * The constructor accessible from Java.
+    * 
+    * @param expected 
+    * @param actual 
+    */
+   public AssertionFailedError(final BaseDataType expected, final BaseDataType actual)
+   {
+      this.expected = expected;
+      this.actual = actual;
+   }
+   
+   /**
+    * Initialize using the message describing the failure.
+    * 
+    * @param msgtxt
+    *        the message
+    */
+   @LegacySignature(type = Type.CONSTRUCTOR, parameters = 
+   {
+      @LegacyParameter(name = "msgtxt", type = "CHARACTER", mode = "INPUT")
+   })
+   @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
+   public void __core_AssertionFailedError_constructor__(final character msgtxt)
+   {
+      internalProcedure(this, "__core_AssertionFailedError_constructor__", new Block((Body) () -> 
+      {
+         __core_AssertionFailedError_constructor__(msgtxt, new integer(0));
+      }));
+   }
+
+   /**
+    * Initialize using the template for the message describing the failure,
+    * the expected and actual values.
+    * 
+    * @param msgtxt
+    *        the message
+    * @param expected
+    *        the expected value, must not be {@code null}
+    * @param actual 
+    *        the actual value, must not be {@code null}
+    */
+   @LegacySignature(type = Type.CONSTRUCTOR, parameters = 
+   {
+      @LegacyParameter(name = "msgtxt", type = "CHARACTER", mode = "INPUT"),
+      @LegacyParameter(name = "expected", type = "CHARACTER", mode = "INPUT"),
+      @LegacyParameter(name = "actual", type = "CHARACTER", mode = "INPUT")
+   })
+   @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
+   public void __core_AssertionFailedError_constructor__(final character msgtxt,
+            final character expected,
+            final character actual)
+   {
+      internalProcedure(this, "__core_AssertionFailedError_constructor__", new Block((Body) () -> 
+      {
+         __core_AssertionFailedError_constructor__(msgtxt, new integer(0));
+         
+         this.expected = expected;
+         this.actual = actual;
+      }));
+   }
+
+   /**
+    * Initialize using the message describing the failure and the message number.
+    * 
+    * @param msgtxt
+    *        the message
+    * @param msgnum
+    *        the message number
+    */
+   @LegacySignature(type = Type.CONSTRUCTOR, parameters = 
+   {
+      @LegacyParameter(name = "msgtxt", type = "CHARACTER", mode = "INPUT"),
+      @LegacyParameter(name = "msgnum", type = "INTEGER", mode = "INPUT")
+   })
+   @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
+   public void __core_AssertionFailedError_constructor__(final character msgtxt, final integer msgnum)
+   {
+      internalProcedure(this, "__core_AssertionFailedError_constructor__", new Block((Body) () -> 
+      {
+         __lang_AppError_constructor__(msgtxt, msgnum);
+         msg = msgtxt.getValue();
+      }));
+   }
+
+   /**
+    * Initialize the procedure
+    */
    public void __core_AssertionFailedError_execute__()
    {
       externalProcedure(AssertionFailedError.this, new Block((Body) () -> 
       {
-         {
-         }
-      }));
-   }
-
-   @LegacySignature(type = Type.CONSTRUCTOR, parameters = 
-   {
-      @LegacyParameter(name = "msgtxt", type = "CHARACTER", mode = "INPUT"),
-      @LegacyParameter(name = "msgnum", type = "INTEGER", mode = "INPUT")
-   })
-   @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
-   public void __core_AssertionFailedError_constructor__(final character _msgtxt, final integer _msgnum)
-   {
-      internalProcedure(this, "__core_AssertionFailedError_constructor__", new Block((Body) () -> 
-      {
-         __lang_AppError_constructor__(_msgtxt, _msgnum);
-         _msg = _msgtxt.getValue();
-      }));
-   }
-
-   @LegacySignature(type = Type.CONSTRUCTOR, parameters = 
-   {
-      @LegacyParameter(name = "msgtxt", type = "CHARACTER", mode = "INPUT")
-   })
-   @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
-   public void __core_AssertionFailedError_constructor__(final character _msgtxt)
-   {
-      internalProcedure(this, "__core_AssertionFailedError_constructor__", new Block((Body) () -> 
-      {
-         __core_AssertionFailedError_constructor__(_msgtxt, new integer(0));
-      }));
-   }
-
+         // no-op
+      }));
+   }
+
+   /**
+    * Get the actual value, if set. Otherwise return {@code null}.
+    * 
+    * @return see above
+    */
+   public BaseDataType getActual()
+   {
+      return actual;
+   }
+
+   /**
+    * Get the expected value, if set. Otherwise return {@code null}.
+    * 
+    * @return see above
+    */
+   public BaseDataType getExpected()
+   {
+      return expected;
+   }
+
+   /**
+    * Get failure message. If the failure message was explicitly set in the constructor, then return this message.
+    * Otherwise construct the message using the expected and actual values.
+    * 
+    * @return see above
+    */
    @LegacySignature(returns = "CHARACTER", type = Type.METHOD, name = "GetMessage")
    @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_FULL)
-   public character getMessage()
+   public character getMessageChar()
    {
       return function(this, "GetMessage", character.class, new Block((Body) () -> 
       {
-         returnNormal(new character(_msg));
+         returnNormal(msg == null
+                  ? substitute("Expected: &1 but was: &2", expected, actual)
+                  : new character(msg)); 
       }));
    }
+
+   /**
+    * Get the message string.
+    * 
+    * @return see above
+    */
+   public String getMessage()
+   {
+      return msg;
+   }
+
+   /**
+    * The object implements the writeExternal method to save its contents
+    * by calling the methods of DataOutput for its primitive values or
+    * calling the writeObject method of ObjectOutput for objects, strings,
+    * and arrays.
+    *
+    * @serialData Overriding methods should use this tag to describe
+    *             the data layout of this Externalizable object.
+    *             List the sequence of element types and, if possible,
+    *             relate the element to a public/protected field and/or
+    *             method of this Externalizable class.
+    *
+    * @param out the stream to write the object to
+    * @exception IOException Includes any I/O exceptions that may occur
+    */
+   @Override
+   public void writeExternal(ObjectOutput out) throws IOException
+   {
+      super.writeExternal(out);
+      
+      out.writeObject(actual);
+      out.writeObject(expected);
+      out.writeObject(msg);      
+   }
+
+   /**
+    * The object implements the readExternal method to restore its
+    * contents by calling the methods of DataInput for primitive
+    * types and readObject for objects, strings and arrays.  The
+    * readExternal method must read the values in the same sequence
+    * and with the same types as were written by writeExternal.
+    *
+    * @param in the stream to read data from in order to restore the object
+    * @exception IOException if I/O errors occur
+    * @exception ClassNotFoundException If the class for an object being
+    *              restored cannot be found.
+    */
+   @Override
+   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+   {
+      super.readExternal(in);
+      
+      actual = (BaseDataType) in.readObject();
+      expected = (BaseDataType) in.readObject();
+      msg = (String) in.readObject();
+   }
 }

=== modified file 'src/com/goldencode/p2j/oo/core/system/ApplicationError.java'
--- src/com/goldencode/p2j/oo/core/system/ApplicationError.java	2022-01-20 16:27:48 +0000
+++ src/com/goldencode/p2j/oo/core/system/ApplicationError.java	2022-11-15 19:42:34 +0000
@@ -12,7 +12,8 @@
 **                  Do not use TypeFactory.object for internal usages, use ObjectVar if the reference must 
 **                  be tracked.
 **                  All TypeFactory.object variable definitions must be done outside of the top-level block.
- */
+**     VVT 2022zzzz Serialization support added (see #4658).
+*/
 
 /*
  ** This program is free software: you can redistribute it and/or modify
@@ -77,11 +78,11 @@
 import static com.goldencode.p2j.util.BlockManager.*;
 import static com.goldencode.p2j.util.InternalEntry.Type;
 
+import java.io.*;
 import java.util.HashMap;
 import java.util.Map;
 
-import com.goldencode.p2j.oo.lang.LegacyClass;
-import com.goldencode.p2j.oo.lang._BaseObject_;
+import com.goldencode.p2j.oo.lang.*;
 import com.goldencode.p2j.security.ContextLocal;
 
 /**
@@ -95,6 +96,7 @@
    // this could be a plain static object maybe, not sure if context local works
    private static ContextLocal<Map<Class, String[]>> errorDefinitions = new ContextLocal<Map<Class, String[]>>()
    {
+      @Override
       protected Map<Class, String[]> initialValue()
       {
          return new HashMap<Class, String[]>();
@@ -253,6 +255,49 @@
       }));
    }
 
+   /**
+    * The object implements the writeExternal method to save its contents
+    * by calling the methods of DataOutput for its primitive values or
+    * calling the writeObject method of ObjectOutput for objects, strings,
+    * and arrays.
+    *
+    * @serialData Overriding methods should use this tag to describe
+    *             the data layout of this Externalizable object.
+    *             List the sequence of element types and, if possible,
+    *             relate the element to a public/protected field and/or
+    *             method of this Externalizable class.
+    *
+    * @param out the stream to write the object to
+    * @exception IOException Includes any I/O exceptions that may occur
+    */
+   @Override
+   public void writeExternal(final ObjectOutput out) throws IOException
+   {
+      super.writeExternal(out);
+      
+      out.writeObject(innerError);
+   }
+
+   /**
+    * The object implements the readExternal method to restore its
+    * contents by calling the methods of DataInput for primitive
+    * types and readObject for objects, strings and arrays.  The
+    * readExternal method must read the values in the same sequence
+    * and with the same types as were written by writeExternal.
+    *
+    * @param in the stream to read data from in order to restore the object
+    * @exception IOException if I/O errors occur
+    * @exception ClassNotFoundException If the class for an object being
+    *              restored cannot be found.
+    */
+   @Override
+   public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException
+   {
+      super.readExternal(in);
+      
+      innerError = (object<? extends LegacyError>) in.readObject();
+   }
+
    protected String[] getErrorDefinition()
    {
       Map<Class, String[]> defs = errorDefinitions.get();

=== modified file 'src/com/goldencode/p2j/oo/dataadmin/error/DataAdminError.java'
--- src/com/goldencode/p2j/oo/dataadmin/error/DataAdminError.java	2021-02-21 16:25:50 +0000
+++ src/com/goldencode/p2j/oo/dataadmin/error/DataAdminError.java	2022-11-15 19:43:42 +0000
@@ -2,7 +2,7 @@
 ** Module   : DataAdminError.java
 ** Abstract : Implementation of the builtin class.
 **
-** Copyright (c) 2019-2021, Golden Code Development Corporation.
+** Copyright (c) 2019-2022, Golden Code Development Corporation.
 **
 ** -#- -I- --Date-- -------------------------------Description--------------------------------
 ** 001 CA  20190526 First version, stubs taken by converting the skeleton using FWD.
@@ -10,6 +10,7 @@
 ** 002 CA  20191024 Added method support levels and updated the class support level.
 ** 003 CA  20210221 Fixed 'qualified', 'extent' and 'returns' annotations at the legacy
 **                  signature.
+** 004 VVT 2022zzzz Serialization support added (see #4658).
 */
 
 /*
@@ -74,6 +75,8 @@
 import static com.goldencode.p2j.report.ReportConstants.*;
 import static com.goldencode.p2j.util.InternalEntry.Type;
 
+import java.io.*;
+
 /**
  * Business logic (converted to Java from the 4GL source code
  * in OpenEdge/DataAdmin/Error/DataAdminError.cls).
@@ -91,8 +94,7 @@
    {
       externalProcedure(DataAdminError.this, new Block((Body) () -> 
       {
-         {
-         }
+         // no-op
       }));
    }
 
@@ -187,4 +189,50 @@
          __lang_AppError_constructor__();
       }));
    }
+   
+   /**
+    * The object implements the writeExternal method to save its contents
+    * by calling the methods of DataOutput for its primitive values or
+    * calling the writeObject method of ObjectOutput for objects, strings,
+    * and arrays.
+    *
+    * @serialData Overriding methods should use this tag to describe
+    *             the data layout of this Externalizable object.
+    *             List the sequence of element types and, if possible,
+    *             relate the element to a public/protected field and/or
+    *             method of this Externalizable class.
+    *
+    * @param out the stream to write the object to
+    * @exception IOException Includes any I/O exceptions that may occur
+    */
+   @Override
+   public void writeExternal(ObjectOutput out) throws IOException
+   {
+      super.writeExternal(out);
+      
+      out.writeObject(httperrorNum);
+      out.writeObject(innerError);
+   }
+
+   /**
+    * The object implements the readExternal method to restore its
+    * contents by calling the methods of DataInput for primitive
+    * types and readObject for objects, strings and arrays.  The
+    * readExternal method must read the values in the same sequence
+    * and with the same types as were written by writeExternal.
+    *
+    * @param in the stream to read data from in order to restore the object
+    * @exception IOException if I/O errors occur
+    * @exception ClassNotFoundException If the class for an object being
+    *              restored cannot be found.
+    */
+   @Override
+   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+   {
+      super.readExternal(in);
+      
+      httperrorNum = (integer) in.readObject();
+      innerError = (object<? extends LegacyError>) in.readObject();
+   }
+
 }

=== modified file 'src/com/goldencode/p2j/oo/json/JsonParserError.java'
--- src/com/goldencode/p2j/oo/json/JsonParserError.java	2021-09-17 15:14:10 +0000
+++ src/com/goldencode/p2j/oo/json/JsonParserError.java	2022-11-15 19:44:16 +0000
@@ -2,7 +2,7 @@
 ** Module   : JsonParserError.java
 ** Abstract : Implementation of the Progress.Json.JsonParserError builtin class.
 **
-** Copyright (c) 2019-2021, Golden Code Development Corporation.
+** Copyright (c) 2019-2022, Golden Code Development Corporation.
 **
 ** -#- -I- --Date-- -------------------------------Description--------------------------------
 ** 001 GES 20190307 First version.
@@ -13,6 +13,7 @@
 ** 006 CA  20210221 Fixed 'qualified', 'extent' and 'returns' annotations at the legacy
 **                  signature.
 **     VVT 20210917 Javadoc fixed. 
+** 007 VVT 2022zzzz Serialization support added (see #4658).
 */
 
 /*
@@ -76,6 +77,8 @@
 import static com.goldencode.p2j.report.ReportConstants.*;
 import static com.goldencode.p2j.util.InternalEntry.Type;
 
+import java.io.*;
+
 /**
  * The replacement for the built-in Progress.Json.JsonParserError.
  */
@@ -95,8 +98,7 @@
    {
       externalProcedure(JsonParserError.this, new Block((Body) () -> 
       {
-         {
-         }
+         // no-op
       }));
    }
 
@@ -204,4 +206,48 @@
    {
       return ObjectOps.newInstance(JsonParserError.class, "II", msg, num);
    }
+   
+   /**
+    * The object implements the writeExternal method to save its contents
+    * by calling the methods of DataOutput for its primitive values or
+    * calling the writeObject method of ObjectOutput for objects, strings,
+    * and arrays.
+    *
+    * @serialData Overriding methods should use this tag to describe
+    *             the data layout of this Externalizable object.
+    *             List the sequence of element types and, if possible,
+    *             relate the element to a public/protected field and/or
+    *             method of this Externalizable class.
+    *
+    * @param out the stream to write the object to
+    * @exception IOException Includes any I/O exceptions that may occur
+    */
+   @Override
+   public void writeExternal(ObjectOutput out) throws IOException
+   {
+      super.writeExternal(out);
+      
+      out.writeObject(offset);      
+   }
+
+   /**
+    * The object implements the readExternal method to restore its
+    * contents by calling the methods of DataInput for primitive
+    * types and readObject for objects, strings and arrays.  The
+    * readExternal method must read the values in the same sequence
+    * and with the same types as were written by writeExternal.
+    *
+    * @param in the stream to read data from in order to restore the object
+    * @exception IOException if I/O errors occur
+    * @exception ClassNotFoundException If the class for an object being
+    *              restored cannot be found.
+    */
+   @Override
+   public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException
+   {
+      super.readExternal(in);
+      
+      offset = (integer) in.readObject();
+   }
+
 }

=== modified file 'src/com/goldencode/p2j/oo/lang/AppError.java'
--- src/com/goldencode/p2j/oo/lang/AppError.java	2022-08-30 17:34:17 +0000
+++ src/com/goldencode/p2j/oo/lang/AppError.java	2022-11-15 19:44:53 +0000
@@ -16,7 +16,8 @@
  ** 008 ME  20200409 Add new static factory methods to create AppError.
  ** 009 CA  20210221 Fixed 'qualified', 'extent' and 'returns' annotations at the legacy
  **                  signature.
-**     VVT  20220830 Missing Javadoc added; missing @Override annotations added.
+ ** 010 VVT 20220830 Missing Javadoc added; missing @Override annotations added.
+ **     VVT 2022zzzz Serialization support added (see #4658).
  */
 
 /*
@@ -77,6 +78,8 @@
 import static com.goldencode.p2j.report.ReportConstants.*;
 import static com.goldencode.p2j.util.BlockManager.*;
 
+import java.io.*;
+
 import com.goldencode.p2j.util.*;
 import com.goldencode.p2j.util.InternalEntry.*;
 
@@ -294,4 +297,49 @@
    {
       super.addMessage(msg,  num);
    }
+
+   /**
+    * The object implements the writeExternal method to save its contents
+    * by calling the methods of DataOutput for its primitive values or
+    * calling the writeObject method of ObjectOutput for objects, strings,
+    * and arrays.
+    *
+    * @serialData Overriding methods should use this tag to describe
+    *             the data layout of this Externalizable object.
+    *             List the sequence of element types and, if possible,
+    *             relate the element to a public/protected field and/or
+    *             method of this Externalizable class.
+    *
+    * @param out the stream to write the object to
+    * @exception IOException Includes any I/O exceptions that may occur
+    */
+   @Override
+   public void writeExternal(final ObjectOutput out) throws IOException
+   {
+      super.writeExternal(out);
+      
+      out.writeObject(returnValue);
+      out.writeBoolean(fromReturn);
+   }
+
+   /**
+    * The object implements the readExternal method to restore its
+    * contents by calling the methods of DataInput for primitive
+    * types and readObject for objects, strings and arrays.  The
+    * readExternal method must read the values in the same sequence
+    * and with the same types as were written by writeExternal.
+    *
+    * @param in the stream to read data from in order to restore the object
+    * @exception IOException if I/O errors occur
+    * @exception ClassNotFoundException If the class for an object being
+    *              restored cannot be found.
+    */
+   @Override
+   public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException
+   {
+      super.readExternal(in);
+      
+      returnValue = (character) in.readObject();
+      fromReturn = in.readBoolean();
+   }
 }

=== modified file 'src/com/goldencode/p2j/oo/lang/LegacyEnum.java'
--- src/com/goldencode/p2j/oo/lang/LegacyEnum.java	2022-10-28 10:54:33 +0000
+++ src/com/goldencode/p2j/oo/lang/LegacyEnum.java	2022-11-15 19:45:35 +0000
@@ -18,6 +18,7 @@
 ** 005 CA  20210221 Fixed 'qualified', 'extent' and 'returns' annotations at the legacy
 **                  signature.
 **     TJD 20220504 Java 11 compatibility minor changes
+**     VVT 2022zzzz Serialization support added (see #4658).
 */
 
 /*
@@ -78,6 +79,7 @@
 import static com.goldencode.p2j.report.ReportConstants.*;
 import static com.goldencode.p2j.util.InternalEntry.Type;
 
+import java.io.*;
 import java.util.*;
 import java.util.stream.*;
 import java.util.function.*;
@@ -91,7 +93,7 @@
 @LegacyResourceSupport(supportLvl = CVT_LVL_FULL | RT_LVL_FULL)
 public class LegacyEnum
 extends BaseObject
-implements Comparable<LegacyEnum>
+implements Comparable<LegacyEnum>, Externalizable
 {
    /** Maps enum classes to their control record. */
    private static final Map<Class<?>, EnumControlRecord> registry = new IdentityHashMap<>();
@@ -101,10 +103,10 @@
                                          "of method \"ToObject\"";
    
    /** The case-preserved legacy name for the enum. */
-   protected final String name;
+   protected String name;
 
    /** The 64-bit enum value. */
-   protected final long value;
+   protected long value;
    
    /** Override for the symbol name in cases where it is different from the enum name. */
    private String symname = null;
@@ -723,6 +725,49 @@
    }
    
    /**
+    * The object implements the writeExternal method to save its contents
+    * by calling the methods of DataOutput for its primitive values or
+    * calling the writeObject method of ObjectOutput for objects, strings,
+    * and arrays.
+    *
+    * @serialData Overriding methods should use this tag to describe
+    *             the data layout of this Externalizable object.
+    *             List the sequence of element types and, if possible,
+    *             relate the element to a public/protected field and/or
+    *             method of this Externalizable class.
+    *
+    * @param out the stream to write the object to
+    * @exception IOException Includes any I/O exceptions that may occur
+    */
+   @Override
+   public void writeExternal(final ObjectOutput out) throws IOException
+   {
+      out.writeUTF(name);
+      out.writeLong(value);
+      out.writeUTF(symname);
+   }
+
+   /**
+    * The object implements the readExternal method to restore its
+    * contents by calling the methods of DataInput for primitive
+    * types and readObject for objects, strings and arrays.  The
+    * readExternal method must read the values in the same sequence
+    * and with the same types as were written by writeExternal.
+    *
+    * @param in the stream to read data from in order to restore the object
+    * @exception IOException if I/O errors occur
+    * @exception ClassNotFoundException If the class for an object being
+    *              restored cannot be found.
+    */
+   @Override
+   public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException
+   {
+      name = in.readUTF();
+      value = in.readLong();
+      symname = in.readUTF();      
+   }
+
+   /**
     * Return the enum instance of the given type which is associated with the provided value.
     *
     * @param    <T>
@@ -1657,4 +1702,5 @@
          this.valueSort       = valueSort;
       }
    }
+
 }

=== modified file 'src/com/goldencode/p2j/oo/lang/ProError.java'
--- src/com/goldencode/p2j/oo/lang/ProError.java	2022-02-09 14:18:48 +0000
+++ src/com/goldencode/p2j/oo/lang/ProError.java	2022-11-15 19:46:07 +0000
@@ -17,6 +17,7 @@
 ** 009 CA  20210221 Fixed 'qualified', 'extent' and 'returns' annotations at the legacy
 **                  signature.
 **     CA  20220208 Implemented the callstack property.
+**     VVT 2022zzzz Serialization support added (see #4658).
 */
 
 /*
@@ -74,14 +75,15 @@
 
 package com.goldencode.p2j.oo.lang;
 
+import static com.goldencode.p2j.report.ReportConstants.*;
 import static com.goldencode.p2j.util.BlockManager.*;
-import static com.goldencode.p2j.report.ReportConstants.*;
 
+import java.io.*;
 import java.util.*;
 
 import com.goldencode.p2j.*;
 import com.goldencode.p2j.util.*;
-import com.goldencode.p2j.util.InternalEntry.Type;
+import com.goldencode.p2j.util.InternalEntry.*;
 
 /**
  * Implementation of the Progress.Lang.ProError builtin class.
@@ -90,13 +92,13 @@
 @LegacyResourceSupport(supportLvl = CVT_LVL_FULL|RT_LVL_BASIC)
 public class ProError
 extends BaseObject
-implements LegacyError
+implements LegacyError, Externalizable
 {
    /** The severity property. */
-   protected final integer severity = new integer(0);
+   protected integer severity = new integer(0);
    
    /** The recorded errors. */
-   protected final List<NumberedException> errors = new ArrayList<>();
+   protected List<NumberedException> errors = new ArrayList<>();
    
    /** The call stack at the time the error was thrown. */
    private String callStack = null;
@@ -138,6 +140,7 @@
    {
       externalProcedure(this, new Block((Body) () -> 
       {
+         // no-op
       }));
    }
 
@@ -307,6 +310,7 @@
     *           
     * @return   The error message for the specified error.
     */
+   @Override
    @LegacySignature(returns = "CHARACTER", type = Type.METHOD, name = "GetMessage", parameters = 
    {
       @LegacyParameter(name = "idx", type = "INTEGER", mode = "INPUT")
@@ -330,6 +334,7 @@
     *           
     * @return   The error message number for the specified error.
     */
+   @Override
    @LegacySignature(returns = "INTEGER", type = Type.METHOD, name = "GetMessageNum", parameters = 
    {
       @LegacyParameter(name = "idx",  type = "INTEGER", mode = "INPUT"),
@@ -361,6 +366,48 @@
    }
    
    /**
+    * The object implements the writeExternal method to save its contents
+    * by calling the methods of DataOutput for its primitive values or
+    * calling the writeObject method of ObjectOutput for objects, strings,
+    * and arrays.
+    *
+    * @serialData Overriding methods should use this tag to describe
+    *             the data layout of this Externalizable object.
+    *             List the sequence of element types and, if possible,
+    *             relate the element to a public/protected field and/or
+    *             method of this Externalizable class.
+    *
+    * @param out the stream to write the object to
+    * @exception IOException Includes any I/O exceptions that may occur
+    */
+   @Override
+   public void writeExternal(final ObjectOutput out) throws IOException
+   {
+      out.writeObject(severity);
+      out.writeObject(errors);
+      out.writeObject(callStack);      
+   }
+
+   /**
+    * The object implements the readExternal method to restore its
+    * contents by calling the methods of DataInput for primitive
+    * types and readObject for objects, strings and arrays.  The
+    * readExternal method must read the values in the same sequence
+    * and with the same types as were written by writeExternal.
+    *
+    * @param in the stream to read data from in order to restore the object
+    * @exception IOException if I/O errors occur
+    * @exception ClassNotFoundException If the class for an object being
+    *              restored cannot be found.
+    */
+   @Override
+   public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException
+   {
+      severity = (integer) in.readObject();
+      errors   = (List<NumberedException>) in.readObject();
+      callStack = (String) in.readObject();
+   }
+   /**
     * Check if the specified index is valid for {@link #errors}.
     * 
     * @param    idx
@@ -383,4 +430,5 @@
       
       return true;
    }
+
 }

=== modified file 'src/com/goldencode/p2j/oo/lang/SoapFaultError.java'
--- src/com/goldencode/p2j/oo/lang/SoapFaultError.java	2021-02-21 16:25:50 +0000
+++ src/com/goldencode/p2j/oo/lang/SoapFaultError.java	2022-11-15 19:46:36 +0000
@@ -2,7 +2,7 @@
 ** Module   : SoapFaultError.java
 ** Abstract : Implementation of the builtin class.
 **
-** Copyright (c) 2019-2021, Golden Code Development Corporation.
+** Copyright (c) 2019-2022, Golden Code Development Corporation.
 **
 ** -#- -I- --Date-- -------------------------------Description--------------------------------
 ** 001 CA  20190526 First version, stubs taken by converting the skeleton using FWD.
@@ -10,6 +10,7 @@
 ** 002 CA  20191024 Added method support levels and updated the class support level.
 ** 003 CA  20210221 Fixed 'qualified', 'extent' and 'returns' annotations at the legacy
 **                  signature.
+** 004 VVT 2022zzzz Serialization support added (see #4658).
 */
 
 /*
@@ -67,12 +68,13 @@
 
 package com.goldencode.p2j.oo.lang;
 
+import static com.goldencode.p2j.report.ReportConstants.*;
+import static com.goldencode.p2j.util.BlockManager.*;
+
+import java.io.*;
+
 import com.goldencode.p2j.util.*;
-import com.goldencode.p2j.oo.lang.*;
-
-import static com.goldencode.p2j.util.BlockManager.*;
-import static com.goldencode.p2j.report.ReportConstants.*;
-import static com.goldencode.p2j.util.InternalEntry.Type;
+import com.goldencode.p2j.util.InternalEntry.*;
 
 /**
  * Business logic (converted to Java from the 4GL source code
@@ -89,8 +91,7 @@
    {
       externalProcedure(SoapFaultError.this, new Block((Body) () -> 
       {
-         {
-         }
+         // no-op
       }));
    }
 
@@ -113,4 +114,48 @@
          returnNormal(soapFault);
       }));
    }
+   
+   /**
+    * The object implements the writeExternal method to save its contents
+    * by calling the methods of DataOutput for its primitive values or
+    * calling the writeObject method of ObjectOutput for objects, strings,
+    * and arrays.
+    *
+    * @serialData Overriding methods should use this tag to describe
+    *             the data layout of this Externalizable object.
+    *             List the sequence of element types and, if possible,
+    *             relate the element to a public/protected field and/or
+    *             method of this Externalizable class.
+    *
+    * @param out the stream to write the object to
+    * @exception IOException Includes any I/O exceptions that may occur
+    */
+   @Override
+   public void writeExternal(final ObjectOutput out) throws IOException
+   {
+      super.writeExternal(out);
+      
+      out.writeObject(soapFault);      
+   }
+
+   /**
+    * The object implements the readExternal method to restore its
+    * contents by calling the methods of DataInput for primitive
+    * types and readObject for objects, strings and arrays.  The
+    * readExternal method must read the values in the same sequence
+    * and with the same types as were written by writeExternal.
+    *
+    * @param in the stream to read data from in order to restore the object
+    * @exception IOException if I/O errors occur
+    * @exception ClassNotFoundException If the class for an object being
+    *              restored cannot be found.
+    */
+   @Override
+   public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException
+   {
+      super.readExternal(in);
+      
+      soapFault = (handle) in.readObject();
+   }
+
 }

=== modified file 'src/com/goldencode/p2j/oo/net/http/HttpRequestError.java'
--- src/com/goldencode/p2j/oo/net/http/HttpRequestError.java	2020-12-17 07:29:53 +0000
+++ src/com/goldencode/p2j/oo/net/http/HttpRequestError.java	2022-11-15 19:47:06 +0000
@@ -2,12 +2,12 @@
 ** Module   : HttpRequestError.java
 ** Abstract : Implementation of the builtin class.
 **
-** Copyright (c) 2020, Golden Code Development Corporation.
+** Copyright (c) 2022, Golden Code Development Corporation.
 **
 ** -#- -I- --Date-- -------------------------------Description--------------------------------
 ** 001 MP  20200603 First version, stubs taken by converting the skeleton using FWD.
 ** 002 ME  20201214 Implement as of OE12.2.
-** 
+** 003 VVT 2022zzzz Serialization support added (see #4658).
 */
 
 /*
@@ -91,6 +91,7 @@
       {
          onBlockLevel(Condition.ERROR, Action.THROW);
          {
+            // no-op
          }
       }));
    }

=== modified file 'src/com/goldencode/p2j/oo/web/SendExceptionError.java'
--- src/com/goldencode/p2j/oo/web/SendExceptionError.java	2021-09-10 07:10:03 +0000
+++ src/com/goldencode/p2j/oo/web/SendExceptionError.java	2022-11-15 19:47:36 +0000
@@ -2,10 +2,11 @@
 ** Module   : SendExceptionError.java
 ** Abstract : Implementation of the builtin class.
 **
-** Copyright (c) 2019-2021, Golden Code Development Corporation.
+** Copyright (c) 2019-2022, Golden Code Development Corporation.
 **
 ** -#- -I- --Date-- -------------------------------Description--------------------------------
 ** 001 ME  20210910 First version, stubs taken by converting the skeleton using FWD.
+** 002 VVT 2022zzzz Serialization support added (see #4658).
 */
 
 /*
@@ -68,8 +69,10 @@
 import static com.goldencode.p2j.util.BlockManager.*;
 import static com.goldencode.p2j.util.InternalEntry.Type;
 
+import java.io.*;
+
 import com.goldencode.p2j.oo.core.Assert;
-import com.goldencode.p2j.oo.net.http.StatusCodeHelper;
+import com.goldencode.p2j.oo.net.http.*;
 
 /**
  * Business logic (converted to Java from the 4GL source code
@@ -94,8 +97,7 @@
       }, 
       (Body) () -> 
       {
-         {
-         }
+         // no-op
       }));
    }
 
@@ -230,4 +232,22 @@
          __web_SendExceptionError_constructor__(p1, StatusCodeHelper.getMessage(p1), p2);
       }));
    }
+
+   @Override
+   public void writeExternal(final ObjectOutput out) throws IOException
+   {
+      super.writeExternal(out);
+      
+      out.writeObject(statusCode);
+      out.writeObject(statusMessage);
+   }
+
+   @Override
+   public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException
+   {
+      super.readExternal(in);
+      
+      statusCode = (object<? extends StatusCodeEnum>) in.readObject();
+      statusMessage = (character) in.readObject();
+   }
 }

=== modified file 'src/com/goldencode/p2j/util/object.java'
--- src/com/goldencode/p2j/util/object.java	2022-03-28 10:47:28 +0000
+++ src/com/goldencode/p2j/util/object.java	2022-11-15 19:50:52 +0000
@@ -32,6 +32,7 @@
 **                  initialized at the method's execution, and not at the caller's arguments.
 **     CA  20220304 Fixed 'invalid handle' error message text.
 **     AL2 20220319 Added value proxy check in assign.
+**     VVT 2022zzzz Serialization support added (see #4658).
 */
 
 /*
@@ -199,6 +200,7 @@
     * 
     * @return   type
     */
+   @Override
    public Type getType()
    {
       return Type.OBJECT;
@@ -296,6 +298,7 @@
     *
     * @return  The hash code for this object instance.
     */
+   @Override
    public int hashCode()
    {
       int result = 17;
@@ -355,6 +358,7 @@
     * @param    value
     *           The instance from which to copy state.
     */
+   @Override
    public void assign(BaseDataType value)
    {
       if (value != null)
@@ -426,6 +430,7 @@
     * @param    old
     *           The backup instance from which to copy data.
     */
+   @Override
    public void assign(Undoable old)
    {
       if (old instanceof BaseDataType)
@@ -444,6 +449,7 @@
     * @return   <code>true</code> if this instance is set to the
     *           <code>unknown value</code>.
     */
+   @Override
    public boolean isUnknown()
    {
       return !ObjectOps.isValid(ref);
@@ -488,6 +494,7 @@
     * <p>
     * <b>Warning: the data stored in this instance will be invalid after calling this method.</b>
     */
+   @Override
    public void setUnknown()
    {
       ref = null;
@@ -500,6 +507,7 @@
     *
     * @return   A clone of this instance.
     */
+   @Override
    public BaseDataType duplicate()
    {
       return new object<>(this);
@@ -510,6 +518,7 @@
     *
     * @return   An instance that represents the <code>unknown value</code>.
     */
+   @Override
    public BaseDataType instantiateUnknown()   
    {
       return new object<>();
@@ -525,6 +534,7 @@
     *
     * @return   The formatted string.
     */
+   @Override
    public String toString(String fmt)
    {
       return toStringMessage();
@@ -538,6 +548,7 @@
     *
     * @return   The 'message' formatted string.
     */
+   @Override
    public String toStringMessage()
    {
       return isUnknown() ? "?" : ref.toLegacyString().toStringMessage();
@@ -550,6 +561,7 @@
     *
     * @return   The 'export' formatted string.
     */
+   @Override
    public String toStringExport()
    {
       return toStringMessage();
@@ -560,6 +572,7 @@
     *
     * @return   The default format string.
     */
+   @Override
    public String defaultFormatString()
    {
       // objects can't be formatted
@@ -567,37 +580,44 @@
    }
    
    /**
-    * Replacement for the default object reading method. The latest state is read from the input 
-    * source.
-    * 
-    * @param    in
-    *           The input source from which fields will be restored.
-    *
-    * @throws   NotSerializableException
-    *           Always, as legacy objects can't be serialized.
+    * The object implements the writeExternal method to save its contents
+    * by calling the methods of DataOutput for its primitive values or
+    * calling the writeObject method of ObjectOutput for objects, strings,
+    * and arrays.
+    *
+    * @serialData Overriding methods should use this tag to describe
+    *             the data layout of this Externalizable object.
+    *             List the sequence of element types and, if possible,
+    *             relate the element to a public/protected field and/or
+    *             method of this Externalizable class.
+    *
+    * @param out the stream to write the object to
+    * @exception IOException Includes any I/O exceptions that may occur
     */
-   public void readExternal(ObjectInput in)
-   throws IOException, ClassNotFoundException
+   @Override
+   public void writeExternal(final ObjectOutput out) throws IOException
    {
-      // there is no need to serialize this object
-      throw new NotSerializableException("Legacy objects can't be serialized!");
+      out.writeObject(type);
+      out.writeObject(ref);      
    }
 
    /**
-    * Replacement for the default object writing method. The latest state is written to the output
-    * destination.
-    * 
-    * @param    out
-    *           The output destination to which fields will be saved.
+    * The object implements the readExternal method to restore its
+    * contents by calling the methods of DataInput for primitive
+    * types and readObject for objects, strings and arrays.  The
+    * readExternal method must read the values in the same sequence
+    * and with the same types as were written by writeExternal.
     *
-    * @throws   NotSerializableException
-    *           Always, as legacy objects can't be serialized.
+    * @param in the stream to read data from in order to restore the object
+    * @exception IOException if I/O errors occur
+    * @exception ClassNotFoundException If the class for an object being
+    *              restored cannot be found.
     */
-   public void writeExternal(ObjectOutput out)
-   throws IOException
+   @Override
+   public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException
    {
-      // there is no need to serialize this object
-      throw new NotSerializableException("Legacy objects can't be serialized!");
+      type = (Class<T>) in.readObject();
+      ref = (T) in.readObject();
    }
 
    /**

