Board index » delphi » ESOAPDomConvertError
Graham Harris
Delphi Developer |
Graham Harris
Delphi Developer |
ESOAPDomConvertError2007-03-28 04:07:36 PM delphi53 Hi How do I prevent this area? --------------------------- Error --------------------------- ESOAPDomConvertError Must enable multiref output for objects when serializing a graph of objects - (Pushpin) --------------------------- OK --------------------------- TIA Graham Harris |
Graham Harris
Delphi Developer |
2007-03-28 05:18:10 PM
Re:ESOAPDomConvertError
Hello Graham,
Meant "How do I prevent this error?" Graham Harris QuoteHi |
Jean-Marie Babet
Delphi Developer |
2007-03-29 08:59:32 AM
Re:ESOAPDomConvertError
Hello,
Quote>ESOAPDomConvertError Must enable multiref output for objects when encounter the same object more than once while serializing a request. Since document style does not support multiref, the logic stores the address of each object as it is being serialized, then proceeds to serialize the members(class) or elements(array) of the object. If somewhere there's a cycle and we detect that we're about to serialize an object that we've already serialized, that exception is fired. The type in this case was a Pushpin. If you're sending more than one Pushpin, you will want to make sure that there's a unique object for each, even if they have the same property values. NOTE: it is also possible to run into this in cases where you (a) Use the component to serialize an object to XML and forget to call 'ResetMultiRef'. The next call might encounter the same address already in the object list although it is clearly not a problem as we're in a new call. (b) Have custom TRemotable-derived types that allocate and free objects in ObjectToSOAP [or methods invoked from]. In that case the objects were distinct but allocated the same memory address by the memory manager. In the case where you're just invoking a WebService using types generated by the importer, (a) and (b) don't apply. Let me know if the above does not help and we'll investigate some more. Cheers, Bruneau. |
Graham Harris
Delphi Developer |
2007-03-29 03:34:43 PM
Re:ESOAPDomConvertError
Hello Bruneau,
QuoteHave custom TRemotable-derived types that allocate and free private FIconID: TStockIcon; FCustomIconName: WideString; FObjectID: WideString; function GetIconName(const Value: TStockIcon): WideString; procedure SetIconID(const Value: TStockIcon); public constructor Create; override; procedure Assign(Pin: TMapPointPushPin); procedure SetLabel(Value: WideString); overload; procedure SetLabel(Strings: TStrings); overload; function AsPushPin(StandardIconDataSource, CustomIconDataSource: WideString; CustomIcons: TStrings): PushPin; published property CustomIconName: WideString read FCustomIconName write FCustomIconName; property IconID: TStockIcon read FIconID write SetIconID; property ObjectID: WideString read FObjectID write FObjectID; end; I have posted the imported WSDL and the unit the above code is defined in. Look for the following subject: ESOAPDomConvertError FAO Bruneau TIA Graham Harris |
Jean-Marie Babet
Delphi Developer |
2007-03-30 01:05:09 AM
Re:ESOAPDomConvertError
Hello,
QuoteI have posted the imported WSDL and the unit the above code is defined in. Bruneau. |
Jean-Marie Babet
Delphi Developer |
2007-03-30 03:01:29 AM
Re:ESOAPDomConvertError
Hello,
I see that you have a collection of pushpins. I also see that the Get(Index) member returns the actual object in the collection. I don't see the code that uses that collection but I can imagine a scenario whereby a given request could use the same PushPin [i.e. same Index to 'Get'] more than once. This could result in a case where the following logic catches the same Pushpin: AddObjectAsWriting(Instance); try { NOTE: Don't prefix for simple types } if (IsSimpleClass) then ObjConvOpts := ObjConvOpts + [ocoDontPrefixNode]; CreateObjectNode(Obj, RootNode, InstNode, ExtPropName, ElemURI, ObjConvOpts); finally RemoveObjectAsWriting(Obj); end; Basically before we serialize an object we add to the list by calling 'AddObjectAsWriting'. Then we proceed. We remove the object upon returning. One way to avoid creating a cycle is to make Get(Index) returns a clone object. There's also another danger to Get(Index) returning the object in a collection. The importer generates code in the destructor of TRemotable-derive classes that does a deep cleanup - invoking .Free on class members and arrays of class members. Typically I warn users to watch for cases where they have cycles in a request/response: unlike the serialization code, the cleanup logic does not keep track of objects already cleaned; hence it can result in cyclic calls to .Free. In code that I have that communicates with RPC services, I often have a routine that unhooks all cycles before I invoke .Free on the base object. Could it be that a given request is retrieving the same Pushpin from the collection. If yes, you will need to clone the Pushpin to ensure that an object added via AddObjectAsWriting(....) is removed before it is added again. Please let me know if I am missing something. Cheers, Bruneau. |
Jean-Marie Babet
Delphi Developer |
2007-03-30 03:07:29 AM
Re:ESOAPDomConvertError
Hey.... wait a minute I just noticed something -
The bug was starring right at me:) QuoteAddObjectAsWriting(Instance); check in the fix Thank you - somehow we never caught this before. More later, Bruneau. "Jean-Marie Babet" <XXXX@XXXXX.COM>writes QuoteHello, |
Jean-Marie Babet
Delphi Developer |
2007-03-30 03:23:14 AM
Re:ESOAPDomConvertError
OK, indeed there was a bug in the code whereby we'd add the parent object to
the ObjectWriting list when serializing a class property. However, upon investigating a little I don't think that is related to the issue you're seeing. The current bug, it seems, would result in us failing to detect a cycle if an instance had a property pointing to itself... IOW, I believe the current logic would still catch cycles but would not have caught all cycles. More on this later... Bruneau. |
Graham Harris
Delphi Developer |
2007-03-30 03:13:30 PM
Re:ESOAPDomConvertError
Hi Bruneau
I use the method AsArrayOfPushPin which loops through the list of PushPins and for each pushpin I call the AsPushPin method of TMapPointPushPin Graham Harris |