FoxInCloud
Problem with properties that are derived from a class with methods
Gravatar is a globally recognized avatar based on your email address. Problem with properties that are derived from a class with methods
  Paul
  All
  Feb 13, 2019 @ 05:39pm

Hi,

I have updated to V 2.28.1-beta.2, but I think this problem has been around for a while.

Situation :
public object - DefaultsObject
has a property - Object2

DefaultsObject.Object2 = createobject("SomeClass")

The class SomeClass has properties and methods. For example a method named Method1.

Problem :
The properties are saved/restored correctly, but methods are not recreated properly.

Symptom :
?DefaultsObject.Object2.Method1()

  • should return numeric, but instead returns .T.

objectOfXML_propSet() and related functions work with properties, but don't respect methods.
After being restored by objectOfXML_propSet(), DefaultsObject.Object2 looks like it has methods on it (intellisense shows them), but they don't really exist anymore (cannot step into them, do not work at all) and I assume FiC code has an object decorator somewhere that simply returns .T. if an invalid method call is made.
This call makes the object property a "zombie" :

I thought I would bypass the problem by setting DefaultsObject.wcPropSaveNot = "Object2", but this has not helped and the property is still being processed.
Further speculation :

  1. wcPropSaveNot is not working
  2. the methods-not-recreated problem might extend to more than just properties on public objects

Paul

Gravatar is a globally recognized avatar based on your email address. re: Problem with properties that are derived from a class with methods
  FoxInCloud Support - Thierry N.
  Paul
  Feb 13, 2019 @ 10:06pm

Hi Paul,

Doubtful, cXMLofObject() of abOOP.prg used in the save process saves the class and class library of each contained object, and objectOfXML() of abOOP.prg recreates the object using the same class and classlibrary if ever user action has changed it, or recycles the existing instance.

will create a test case however.

on your side please make sure of the .class and .classLibrary of the restored object.
thanks

cannot step into them, do not work at all

do you mean that if you add a set step on to the method it does not fire?

I assume FiC code has an object decorator somewhere that simply returns .T. if an invalid method call is made

no such thing, just a plain call to your object's method

the methods-not-recreated problem might extend to more than just properties on public objects

what does 'more than just properties' mean?
Methods are never, and can't be, 'recreated' at run time (.writeMethod() only works at design time).

FoxInCloud keeps the object alive, and just swaps its properties; nothing happens on the methods.

If your classLibrary is a prg, you may want to compile it…

wcPropSaveNot is not working

You're right, cXMLofObject() overlooked .wcPropSaveNot; here is a quick fix:

modify command abOOP.prg

replace the cXMLofObject_lPropSave() code by:

* -----------------------------------------
function cXMLofObject_lPropSave(toObj, tcProp, llFIC) && [cXMLofObject() private] {fr} Propriété modifiable à sauvegarder {en} Updateable property to be saved
local lcProp as String
lcProp = ',' + lower(m.tcProp) + ','
return .t.;
 and !PEMstatus(m.toObj, m.tcProp, 1); && {en} Read-only
 and !m.lcProp $ ',' + chrtran(lower('wcPropSave,wcPropSaveNot,_MemberData,Name'), ' ', '') + ','; && ,dataSession,dataSessionID
 and (!m.llFIC or (.T.;
  and m.lcProp $ ',' + Lower(chrtran(nvl(m.toObj.wcPropSave, ''), ' ', '')) + ',';
  and ! m.lcProp $ ',' + Lower(chrtran(nvl(m.toObj.wcPropSaveNot, ''), ' ', '')) + ',';
  );
 and .t.

endfunc
Gravatar is a globally recognized avatar based on your email address. re: Problem with properties that are derived from a class with methods
  Paul
  FoxInCloud Support - Thierry N.
  Feb 19, 2019 @ 08:17pm

I found the problem :

function objectOfXML_object_oClass(lcClass, lcClassLib, loClass) && [Internal] {en} [objectOfXML_object() private] class instance {fr}  [privée de objectOfXML_object()] instance d'une classe
&& 2018-01-10 thn -- {FiC V 2.26.1-beta.1} {en} created
try
	loClass = newobject(m.lcClass, m.lcClassLib, 0)
catch
	loClass = newobject(m.lcClass, m.lcClassLib)
endtry
return m.loClass
endfunc

--> newobject(m.lcClass, m.lcClassLib, 0)
From VFP help : "0 Specifies that the class or object is instantiated without executing any of the event or method code in the class or object. This feature is not supported in runtime applications." (emphasis is mine)
The problem is that using the 0 parameter creates "zombie" methods on the object which are unusable.
Calling NewObject() without the 0 parameter creates an object with usable methods.

I can see why the code is like this, but I suggest an exception is at least made for classes derived from relation and custom - I know this isn't a perfect solution, but the best I have at the moment.
I will be customising the code to behave like this until a better workaround is available.

Also, I noticed that the m.lcClassLib parameter is incorrect in my situation - it is set to sfic.vcx, but really the class is defined in a program file (or .fxp). While this is not correct, it isn't a problem at the moment because the class is found in the "set procedure" and "set classlib" paths anyway.

Paul

Gravatar is a globally recognized avatar based on your email address. re: Problem with properties that are derived from a class with methods
  FoxInCloud Support - Thierry N.
  Paul
  Feb 20, 2019 @ 12:13am

Great debugging again, thanks for sharing

Not sure why we used the 0 parameter, probably to avoid re-running the .init() method when recreating the object instance while the original instance was released by another user. After thinking (or rather guessing) there's no reason why we should not re-run .init().

I suggest we do the other way round:

* ========================================
function objectOfXML_object_oClass(lcClass, lcClassLib, loClass) && [Internal] {en} [objectOfXML_object() private] class instance {fr}  [privée de objectOfXML_object()] instance d'une classe
&& 2018-01-10 thn -- {FiC V 2.26.1-beta.1} {en} created
&& 2019-02-20 thn -- {FiC V 2.28.1-beta.3} {en} https://support.west-wind.com/ReplyMessage.wwt?id=5F317HTX0#5F317HTX0
try
	loClass = newobject(m.lcClass, m.lcClassLib)
catch
	loClass = newobject(m.lcClass, m.lcClassLib, 0)
endtry
return m.loClass
endfunc

m.lcClassLib is equal to m.toObj.ClassLibrary, so VFP rules.

© 1996-2024