AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi PayPal Soap Anbindung
Thema durchsuchen
Ansicht
Themen-Optionen

PayPal Soap Anbindung

Ein Thema von Harry29 · begonnen am 2. Sep 2015 · letzter Beitrag vom 20. Jun 2018
Antwort Antwort
Seite 1 von 2  1 2      
Dennis07

Registriert seit: 19. Sep 2011
Ort: Deutschland
491 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: PayPal Soap Anbindung

  Alt 13. Jun 2018, 18:13
Wenn du schon drei Jahre alte Threads ausgräbst - warum das Leute immer wieder machen entzieht sich meinem Verständnis
https://www.facebook.com/groups/1370...8672088509186/ ...


Es gilt die alte Regel: Wenn keine Erfahrung vorliegt -> nicht dazu posten!
Gut, dann tu das auch nicht! ...
Kenne mich mit der Thematik auch null aus

Mal ganz abgesehen davon: Ich würde es begrüßen, wenn du mal einen angemessenen Ton anschlägst. Auf so ein Anmotzen hab ich hier offen gesagt keinen Bock.
Dennis
  Mit Zitat antworten Zitat
Benutzerbild von makulik
makulik

Registriert seit: 13. Jun 2018
9 Beiträge
 
#2

AW: PayPal Soap Anbindung

  Alt 13. Jun 2018, 21:08
Hallo Zusammen,

Wenn, Ihr mit Eurem merkwürdigen Hin- und Her-Geplänkel hinsichtlich des angemessenen Tons in technischen Foren fertig seid, dann können wir uns ja mal wieder mit dem eigentlichen Problem beschäftigen (wer Lesen kann ist übrigens immer klar im Vorteil).

Derjenige, der das 3 Jahre alte Thema wieder ausgegraben hatte und nach einer Lösung sucht bin ich. Ich hatte eine entsprechende Anfrage in der FB Delphi Developer Group gestellt:

Memory leak with Delphi 10 Seattle generated Soap from PayPal WSDL.

Leider kam da bislang nicht mehr rüber, als wilde Spekulationen, wie die Speicherverwaltung unter Delphi funktioniert.
Embarcadero scheint das Problem ja offenbar nicht zu interessieren, sonst hätte man wohl einen Fix, oder wenigstens Vorschläge für einen Workaround mit einer fundierten Recherche finden können.
Ich habe das exakt gleiche Problem (mit einer wesentlich aktuelleren Delphi Version), und Source Code der Memory-Leaks produziert pflege ich nicht in Produktion zu geben; soviel dazu und genug zum Vorwort.

--------------------------------------------------------

Also zunächst mal liegt das Problem nicht an dem RequesterCredentials Objekt, das für den SOAP Request erzeugt wurde (der Soap.SOAPHeaders.SetOwnsSentHeaders(True); Mechanismus funktioniert wie er soll), sondern das für den SOAP Response vom PayPal Server ebenfalls ein RequesterCredentials SOAP Header (mit leeren Feldern) zurückgesandt wird und vom Parser ein entsprechendes Objekt instanziiert wird.

Das kann man eigentlich auch schön in TiGü's FastMM Stack Trace sehen:

[Optosoapdomconv.TOPToSoapDomConvert.ProcessResponse$qqrxp22System.Classes.TStreamrx27Soap.Intfinfo.TIntfMetaDatarx28Soap.Intfinfo.TIntfMethEntryp31Soap.Invokeregistry.TInvContextp31Soap.Invokeregistry.THea ProcessResponse ist diesbezüglich ziemlich unmissverständlich.

Die SOAP Header werden nun leider nicht automatisch mit dem decodierten SOAP Body Object freigegeben, soweit ich den Source Code analysiert habe.

Die Response Header werden in einer generischen TObjectList<T> von TSOAPHeaders.FInHeaders (oder so) gespeichert, für die die OwnsObjects Eigenschaft auf true gesetzt ist, soweit ich das heute debugged habe.
D.h. im Klartext, dass die Response Header Objekte eigentlich spätestens beim Zerstören des TSOAPHeaders Objekts abgeräumt werden sollten(!) was aber aus irgendeinem obskuren Grund nicht passiert (TObjectList<T> funktioniert eigentlich ausnahmsweise einwandfrei, soweit mir bekannt ist). Daher das finale Memory-Leak.

Was mir beim Debuggen heute auch noch aufgefallen ist, ist dass das in der Liste gespeicherte TSOAPHeader Objekt von der RTTI nicht als RequesterCredentials Typ erkannt wird, sondern als dessen (generierte) Basis Klasse CustomSecurityHeaderType.

Der vom WSDL Component Generator erzeugte Code sieht so aus:

Delphi-Quellcode:
   RequesterCredentials = class(CustomSecurityHeaderType)
   private
   published
   end;
Ich habe versucht mittels

Delphi-Quellcode:
procedure MyProcedure();
var
    headerAccess : ISOAPHeaders;
    respCredentials : RequesterCredentials;
begin
    // ...

    respCredentials := headerAccess.Get(RequesterCredentials) as RequesterCredentials;

    // ...
    respCredentials.Free();
end;
das Header Objekt explizit zu holen und freizugeben, was allerdings scheitert, da das in der Liste gespeicherte Objekt tatsächlich vom Typ CustomSecurityHeaderType ist.

Weiter bin ich heute nicht mehr gekommen, aber ich glaube ich bin der Lösung (dem Workaround) schon ziemlich nahe.

Der ganze generierte Kram aus dem WSDL basiert übrigens als Super-Super Klasse auf TObject, und leider nicht auf TInterfacedObject und entsprechenden Reference Counted Interface Objekten (TRemotable ist leider nur ein TObject ohne Interface), was die ganze Angelegenheit (Speicherverwaltung) wohl erheblich vereinfachen würde.

Sobald ich in der Lage bin Weiteres zur Lösung des Problems beizutragen, werde ich dies hier tun (morgen hoffentlich).

Gruss,
Günther

P.S.:
Wenn irgendjemand weitere konstruktive und fundierte Beiträge zur Lösung des Problems beitragen möchte, ist dies ausdrücklich erwünscht!

Geändert von makulik (13. Jun 2018 um 21:16 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von makulik
makulik

Registriert seit: 13. Jun 2018
9 Beiträge
 
#3

AW: PayPal Soap Anbindung

  Alt 14. Jun 2018, 11:12
Leider ist es so, dass tatsächlich Embarcadero den Fehler (das Memory-Leak) verursacht.

Das Problem ist der folgende Code in der Funktion TSOAPDomConv.ConvertSOAPToObject aus Soap.OPToSOAPDomConv.pas ab Zeile 4768:

Delphi-Quellcode:
function TSOAPDomConv.ConvertSOAPToObject(RootNode, Node: IXMLNode; AClass: TClass;
  const URI, TypeName: InvString; ObjP: Pointer): TObject;

// ...
    if Assigned(Obj) and LegalRef then
    begin
     if (NodeClass <> nil) and (NodeClass <> Obj.ClassType) then
        Obj.Free(); // Dieses Free hat gefehlt, die alte Instanz von Obj dangled nach dem Überschreiben
        Obj := NodeClass.Create;
    end

// ...
Ist auch in der aktuellen Delphi Version (Tokyo) noch vorhanden. Vermutlich gibt es auch noch weitere Stellen die ein ähnliches Problem haben.
TObject ist nun mal nicht ref-counted
Ich werde ein Ticket bei Embarcadero aufmachen.

Gruss,
Günther
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.874 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: PayPal Soap Anbindung

  Alt 14. Jun 2018, 12:24
Dann sollte man die beiden Zeilen aber auch mit begin..end umschliessen.
Markus Kinzler
  Mit Zitat antworten Zitat
Benutzerbild von makulik
makulik

Registriert seit: 13. Jun 2018
9 Beiträge
 
#5

AW: PayPal Soap Anbindung

  Alt 14. Jun 2018, 18:02
Dann sollte man die beiden Zeilen aber auch mit begin..end umschliessen.
Oops, ja natürlich, Danke.
Es hat glücklicherweise trotzdem funktioniert (ein sehr spezieller Fall.)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.073 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: PayPal Soap Anbindung

  Alt 14. Jun 2018, 12:53
Leider ist es so, dass tatsächlich Embarcadero den Fehler (das Memory-Leak) verursacht.

Das Problem ist der folgende Code in der Funktion TSOAPDomConv.ConvertSOAPToObject aus Soap.OPToSOAPDomConv.pas ab Zeile 4768:

Delphi-Quellcode:
function TSOAPDomConv.ConvertSOAPToObject(RootNode, Node: IXMLNode; AClass: TClass;
  const URI, TypeName: InvString; ObjP: Pointer): TObject;

// ...
    if Assigned(Obj) and LegalRef then
    begin
     if (NodeClass <> nil) and (NodeClass <> Obj.ClassType) then
        Obj.Free(); // Dieses Free hat gefehlt, die alte Instanz von Obj dangled nach dem Überschreiben
        Obj := NodeClass.Create;
    end

// ...
Ist auch in der aktuellen Delphi Version (Tokyo) noch vorhanden. Vermutlich gibt es auch noch weitere Stellen die ein ähnliches Problem haben.
TObject ist nun mal nicht ref-counted
Ich werde ein Ticket bei Embarcadero aufmachen.

Gruss,
Günther


Wenn man sich in der Methode den XML-Text vom RootNode anschaut sieht man folgendes:

Code:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:cc="urn:ebay:apis:CoreComponentTypes" xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext" xmlns:ed="urn:ebay:apis:EnhancedDataTypes" xmlns:ebl="urn:ebay:apis:eBLBaseComponents" xmlns:ns="urn:ebay:api:PayPalAPI">
   <SOAP-ENV:Header>
      <Security xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext" xsi:type="wsse:SecurityType"/>
      <RequesterCredentials xmlns="urn:ebay:api:PayPalAPI" xsi:type="ebl:CustomSecurityHeaderType">   <<<--------- Hier ist der Übertäter
         <Credentials xmlns="urn:ebay:apis:eBLBaseComponents" xsi:type="ebl:UserIdPasswordType"/>
      </RequesterCredentials>
   </SOAP-ENV:Header>
   <SOAP-ENV:Body id="_0">
      <RefundTransactionResponse xmlns="urn:ebay:api:PayPalAPI">
         <Timestamp xmlns="urn:ebay:apis:eBLBaseComponents">2018-06-14T11:41:34Z</Timestamp>
         <Ack xmlns="urn:ebay:apis:eBLBaseComponents">Failure</Ack>
         <CorrelationID xmlns="urn:ebay:apis:eBLBaseComponents">ac2341fd2df09</CorrelationID>
         <Errors xmlns="urn:ebay:apis:eBLBaseComponents" xsi:type="ebl:ErrorType">
            <ShortMessage xsi:type="xs:string">Authentication/Authorization Failed</ShortMessage>
            <LongMessage xsi:type="xs:string">You do not have permissions to make this API call</LongMessage>
            <ErrorCode xsi:type="xs:token">10002</ErrorCode>
            <SeverityCode xmlns="urn:ebay:apis:eBLBaseComponents">Error</SeverityCode>
         </Errors>
         <Version xmlns="urn:ebay:apis:eBLBaseComponents">0.000000</Version>
         <Build xmlns="urn:ebay:apis:eBLBaseComponents">000000</Build>
         <RefundTransactionID/>
      </RefundTransactionResponse>
   </SOAP-ENV:Body></SOAP-ENV:Envelope>
Aufgrund von
Code:
xsi:type="ebl:CustomSecurityHeaderType"
wird ja in den Zeilen
Delphi-Quellcode:
  GetElementType(ObjNode, NodeURI, NodeTypeName);
  NodeClass := RemTypeRegistry.URIToClass(NodeURI, NodeTypeName, IsScalar);
die NodeClass auf CustomSecurityHeaderType gesetzt. Mit den bekannten Folgen.

Also Workaround - welche negativen Auswirkungen das hat, muss gesondert untersucht werden - kannst du in der PayPalSvc-Unit ca. bei Zeile 28049 das folgende auskommentieren:
Delphi-Quellcode:
...
RemClassRegistry.RegisterXSClass(CustomSecurityHeaderType, 'urn:ebay:apis:eBLBaseComponents', 'CustomSecurityHeaderType');
...

Dadurch wird RemTypeRegistry.URIToClass nichts finden und NodeClass wird zu nil.
Damit bleibt das Obj (=> RequesterCredentials) erhalten und das Speicherleck ist weg.

Geändert von TiGü (14. Jun 2018 um 12:55 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von makulik
makulik

Registriert seit: 13. Jun 2018
9 Beiträge
 
#7

AW: PayPal Soap Anbindung

  Alt 14. Jun 2018, 18:11
Also Workaround - welche negativen Auswirkungen das hat, muss gesondert untersucht werden - kannst du in der PayPalSvc-Unit ca. bei Zeile 28049 das folgende auskommentieren:
Delphi-Quellcode:
...
RemClassRegistry.RegisterXSClass(CustomSecurityHeaderType, 'urn:ebay:apis:eBLBaseComponents', 'CustomSecurityHeaderType');
...

Dadurch wird RemTypeRegistry.URIToClass nichts finden und NodeClass wird zu nil.
Damit bleibt das Obj (=> RequesterCredentials) erhalten und das Speicherleck ist weg.
Hmm, ich weiss nicht recht. Für die ausgehenden SOAP Requests muss das ja trotzdem funktionieren, und ich weiss nicht ob es so eine gute Idee ist die Klassenregistrierung zu entfernen.

Für einen "sauberen" Workaround (ohne die gefixte Unit in das .dpr direkt einzubinden) dachte ich eher daran den Original Code zu klonen, und den gefixten Converter explizit an das entsprechende Interface zu übergeben.
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.073 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: PayPal Soap Anbindung

  Alt 15. Jun 2018, 08:26
Für einen "sauberen" Workaround (ohne die gefixte Unit in das .dpr direkt einzubinden) dachte ich eher daran den Original Code zu klonen, und den gefixten Converter explizit an das entsprechende Interface zu übergeben.
Wenn das geht, ist dies ein sinnvoller Weg.

Das Problem, fehlerhafte oder schlecht programmierten Code aus dem Framework ersetzen zu müssen, hatte ich auch schon öfters.
Am Einfachsten ist es noch, wenn man von der betreffenden Klasse ableiten kann und die zu überschreibende Methode protected/public und virtual/dynamic ist.
  Mit Zitat antworten Zitat
Benutzerbild von makulik
makulik

Registriert seit: 13. Jun 2018
9 Beiträge
 
#9

AW: PayPal Soap Anbindung

  Alt 15. Jun 2018, 10:06
Für einen "sauberen" Workaround (ohne die gefixte Unit in das .dpr direkt einzubinden) dachte ich eher daran den Original Code zu klonen, und den gefixten Converter explizit an das entsprechende Interface zu übergeben.
Wenn das geht, ist dies ein sinnvoller Weg.

Das Problem, fehlerhafte oder schlecht programmierten Code aus dem Framework ersetzen zu müssen, hatte ich auch schon öfters.
Am Einfachsten ist es noch, wenn man von der betreffenden Klasse ableiten kann und die zu überschreibende Methode protected/public und virtual/dynamic ist.
Ist leider keine virtuelle Methode, aber die Schnittstelle erlaubt es einen eigenen Converter zu konfigurieren.
  Mit Zitat antworten Zitat
Benutzerbild von makulik
makulik

Registriert seit: 13. Jun 2018
9 Beiträge
 
#10

AW: PayPal Soap Anbindung

  Alt 16. Jun 2018, 13:26
Für einen "sauberen" Workaround (ohne die gefixte Unit in das .dpr direkt einzubinden) dachte ich eher daran den Original Code zu klonen, und den gefixten Converter explizit an das entsprechende Interface zu übergeben.


Leider erweist sich diese Hoffnung als Trugschluss

Die Superklasse TRIO von THTTPRIO hat zwar die definierte Eigenschaft Converter vom (Interface) Typ IOPConverter, THTTPRIO will aber dennoch den Typ Soap.TOPToSoapDomConvert.

Was ist denn das für ein #&$**!!@ Design bitteschön???

Also kein "sauberer" Workaround möglich, es bleibt bei dem Patch (den ich jezt auch noch 2x pflegen muss, für Seattle und Tokyo, da andere Änderungen an Soap.OPToSoapDomConvert.pas vorgenommen wurden).
So ein Saftladen!!

P.S.:
Für jeden den's interessiert, hier ist das Ticket bei Embarcadero: RAD StudioRSP-20730

Geändert von makulik (16. Jun 2018 um 13:28 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:59 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz