AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi PayPal Soap Anbindung

PayPal Soap Anbindung

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

Registriert seit: 1. Sep 2015
2 Beiträge
 
#1

PayPal Soap Anbindung

  Alt 2. Sep 2015, 07:20
Hallo zusammen,

ich kämpfe mit einer PayPal Soap Anbindung unter Delphi XE5.
PayPal erwartet einen individuellen Soap Header mit den Zugangsdaten.
In der importierten WSDL steht hier für die Klasse RequesterCredentials (TSoapHeader)bereit.
Hier nun ein einfaches Beispiel eines Aufrufes:

Delphi-Quellcode:
procedure TTest.PayPalTest;
var
  Soap: THTTPRIO;
  PayPal: PayPalAPIInterface;
  Sec: RequesterCredentials;
  Request: RefundTransactionReq;
  Response: RefundTransactionResponse;
begin
  Soap := THTTPRIO.Create(nil);
  try
    CoInitialize(nil);
    PayPal := GetPayPalAPIInterface(False, 'https://api-3t.sandbox.paypal.com/2.0/', Soap);

    Sec := RequesterCredentials.Create;
    Sec.Credentials := UserIdPasswordType.Create;
    Sec.Credentials.Username := 'hello world';
    Sec.Credentials.Password := 'hello world';
    Sec.Credentials.Signature := 'hello world';
    Soap.SOAPHeaders.Send(Sec);
    Soap.SOAPHeaders.SetOwnsSentHeaders(True);

    Request := RefundTransactionReq.Create;
    Request.RefundTransactionRequest := RefundTransactionRequest.Create;
    Response := PayPal.RefundTransaction(Request);
  finally
    FreeAndNil(Response);
    FreeAndNil(Request);
    CoUnInitialize;
  end;
end;
Wenn ich nun das Programm beende, meldet mein FastMM das es ein Speicherloch
im Bereich dieser RequesterCredentials gibt. Verstehe ich nicht, durch SetOwnsSentHeaders wird der Destructor
von RequesterCredentials nach dem Request aufgerufen.

Vielleicht hat hier jemand schon mal PayPal integriert und kann mir einen Tipp geben,
oder vielleicht mache ich generell etwas mit den Headern falsch, auch dann wäre ich um einen Tipp dankbar.
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
38.828 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#2

AW: PayPal Soap Anbindung

  Alt 2. Sep 2015, 07:24
Gib Sec einfach auch im finally frei.
Markus Kinzler
  Mit Zitat antworten Zitat
Harry29

Registriert seit: 1. Sep 2015
2 Beiträge
 
#3

AW: PayPal Soap Anbindung

  Alt 2. Sep 2015, 07:45
Hhm. Nö, durch SetOwnsSentHeaders ist das ja eigentlich schon automatisch freigegeben.
Bein einem zusätzlichen Sec.Free im Finally gibts eine AV von FastMM.

Wenn ich SetOwnSentHeaders ausschalte und im Finally Sec.Free aufrufe,
habe ich im Übrigen weiterhin das Speicherloch.

Geändert von Harry29 ( 2. Sep 2015 um 07:47 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
1.808 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#4

AW: PayPal Soap Anbindung

  Alt 2. Sep 2015, 08:30
Kenne mich mit der Thematik auch null aus, aber wenn man der Klasse RequesterCredentials einen Konstruktor und Destruktor verpasst, werden die auch erwartungsgemäß jeweils einmal durchlaufen.
Daran kann es also nicht liegen.
Wird vielleicht in den Unweiten des Frameworks sowas wie eine Kopie erzeugt?

Falls es jemanden weiterbringt, hier die Meldung vom externen FastMM (mit Delphi XE7):
Code:
--------------------------------2015/9/2 9:26:31--------------------------------
A memory block has been leaked. The size is: 52

This block was allocated by thread 0x474, and the stack trace (return addresses) at the time was:
406CC2 [System.pas][System][@GetMem$qqri][4391]
407AF3 [System.pas][System][TObject.NewInstance$qqrv][15641]
40821A [System.pas][System][@ClassCreate$qqrpvzc][16951]
685B2A [Soap.InvokeRegistry.pas][Soap.InvokeRegistry][Invokeregistry.TRemotable.$bctr$qqrv][2347]
6677E2 [Soap.OPToSOAPDomConv.pas][Soap.OPToSOAPDomConv][Optosoapdomconv.TSOAPDomConv.ReadHeader$qqrx47System.%DelphiInterface$20Xml.Xmlintf.IXMLNode%t1p31Soap.Invokeregistry.THeaderList][925]
66B4C5 [Soap.OPToSOAPDomConv.pas][Soap.OPToSOAPDomConv][Optosoapdomconv.TOPToSoapDomConvert.ProcessResponse$qqrx51System.%DelphiInterface$24Xml.Xmlintf.IXMLDocument%rx27Soap.Intfinfo.TIntfMetaDatarx28Soap.Intfinfo.TIntfMethEntryp31Soap.Invokeregistry.TInvContex
66B975 [Soap.OPToSOAPDomConv.pas][Soap.OPToSOAPDomConv][Optosoapdomconv.TOPToSoapDomConvert.ProcessResponse$qqrxp22System.Classes.TStreamrx27Soap.Intfinfo.TIntfMetaDatarx28Soap.Intfinfo.TIntfMethEntryp31Soap.Invokeregistry.TInvContextp31Soap.Invokeregistry.THea
675C6D [Soap.Rio.pas][Soap.Rio][Rio.TRIO.DoDispatch$qqrxp31Soap.Invokeregistry.TInvContextirx28Soap.Intfinfo.TIntfMethEntry][372]
67651B [Soap.Rio.pas][Soap.Rio][Rio.TRIO.Generic$qqrp23System.Rtti.TRttiMethodx42System.%DynamicArray$18System.Rtti.TValue%r18System.Rtti.TValue][530]
675FF2 [Soap.Rio.pas][Soap.Rio][Rio.TRIO.QueryInterface$15$ActRec.$0$Body$qqrp23System.Rtti.TRttiMethodx42System.%DynamicArray$18System.Rtti.TValue%r18System.Rtti.TValue][430]
469488 [System.Rtti.pas][System.Rtti][Rtti.TVirtualInterface.RawCallback$qqrpvx42System.%DynamicArray$18System.Rtti.TValue%r18System.Rtti.TValue][10027]

The block is currently used for an object of class: RequesterCredentials

The allocation number is: 6384

Current memory dump of 256 bytes starting at pointer address 7EC96C30:
DC AD 69 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 B9 1A 7D 80 80 80 80 00 00 00 00 F1 6D C9 7E
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F9 18 00 00 C2 6C 40 00 F3 7A 40 00 89 D8 40 00
1A 82 40 00 E2 50 60 00 3A 44 FE 76 A0 60 60 00 E8 61 60 00 A5 77 60 00 74 18 67 00 DD 2F 67 00
74 04 00 00 74 04 00 00 DE 6C 40 00 11 7B 40 00 65 82 40 00 69 51 60 00 11 D9 40 00 EB D7 40 00
C1 B4 40 00 B1 B3 40 00 8F 7C 40 00 0A 7B 40 00 65 82 40 00 2C 00 00 00 3C 22 60 00 D4 59 60 FC
90 72 73 00 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 2B A6 9F 03 80 80 80 80 80 80 80 80 00 00 00 00 B1 6E C9 7E
Ü  *  i . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . ¹  . }  €  €  €  €  . . . . ñ  m É  ~
. . . . . . . . . . . . . . . . ù  . . .   l @  . ó  z @  . ‰  Ø  @  .
. ‚  @  . â  P `  . : D þ  v *  `  `  . è  a `  . ¥  w `  . t . g . Ý  /  g .
t . . . t . . . Þ  l @  . . {  @  . e ‚  @  . i Q `  . . Ù  @  . ë  ×  @  .
Á  ´  @  . ±  ³  @  .   |  @  . . {  @  . e ‚  @  . , . . . < " `  . Ô  Y `  ü
  r s . €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  +  ¦  Ÿ  . €  €  €  €  €  €  €  €  . . . . ±  n É  ~

--------------------------------2015/9/2 9:26:31--------------------------------
This application has leaked memory. The small block leaks are (excluding expected leaks registered by pointer):

37 - 52 bytes: RequesterCredentials x 1
  Mit Zitat antworten Zitat
Dennis07

Registriert seit: 19. Sep 2011
Ort: Deutschland
242 Beiträge
 
Delphi XE5 Professional
 
#5

AW: PayPal Soap Anbindung

  Alt 13. Jun 2018, 04:14
Delphi-Quellcode:
procedure TTest.PayPalTest;
var
  Soap: THTTPRIO;
  PayPal: PayPalAPIInterface;
  Sec: RequesterCredentials;
  Request: RefundTransactionReq;
  Response: RefundTransactionResponse;
begin
  Soap := THTTPRIO.Create(nil);
  try
    //...
    Request := RefundTransactionReq.Create;
    Request.RefundTransactionRequest := RefundTransactionRequest.Create;
    Response := PayPal.RefundTransaction(Request);
  finally
    FreeAndNil(Response);
    FreeAndNil(Request);
    CoUnInitialize;
  end;
end;
Ohne mich da jetzt reinlesen zu müssen, kann ich dir sagen, dass so eine Architektur, wie du sie geschrieben hast, nicht gerade sicher ist. Du kannst/solltest keine Objekte im "finally" freigeben, die du im "try" erst erzeugt hast. Das kann ganz leicht zu Zugriffsverletzungen führen. Und zwar beispielsweise immer dann, wenn im Konstruktor ein Fehler passiert, der nicht abgefangen wird. Der richtige Weg wäre 1. das Objekt erzeugen, dann in "try" damit arbeiten und später im "finally" freigeben. Dann bist du immer auf der sicheren Seite. Außerdem: Gewöhne dir an, alle Typen mit einem "T" und alle Interfaces mit einem "I" im Namen zu beginnen. Das macht es einfacher, sie zu identifizieren und von Standardtypen auseinander zu halten. Ich weiß jetzt nämlich zB nicht sicher, was bei dir ein Interface und was ein Klassen/Recordtypen hat. Das ließe sich leicht vermeiden. Ich sehe außerdem, dass du "Request.RefundTransactionRequest" erzeugst, aber nirgendwo freigibst. Ist es ein Interfaced-Typ mit Refcounting? Falls nein: Diesen MUSST du natürlich auch wieder freigeben, es reicht nicht, nur das Mutterobjekt freizugeben.
Dennis
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
1.808 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#6

AW: PayPal Soap Anbindung

  Alt 13. Jun 2018, 08:00
Delphi-Quellcode:
procedure TTest.PayPalTest;
var
  Soap: THTTPRIO;
  PayPal: PayPalAPIInterface;
  Sec: RequesterCredentials;
  Request: RefundTransactionReq;
  Response: RefundTransactionResponse;
begin
  Soap := THTTPRIO.Create(nil);
  try
    //...
    Request := RefundTransactionReq.Create;
    Request.RefundTransactionRequest := RefundTransactionRequest.Create;
    Response := PayPal.RefundTransaction(Request);
  finally
    FreeAndNil(Response);
    FreeAndNil(Request);
    CoUnInitialize;
  end;
end;
Außerdem: Gewöhne dir an, alle Typen mit einem "T" und alle Interfaces mit einem "I" im Namen zu beginnen. Das macht es einfacher, sie zu identifizieren und von Standardtypen auseinander zu halten. Ich weiß jetzt nämlich zB nicht sicher, was bei dir ein Interface und was ein Klassen/Recordtypen hat. Das ließe sich leicht vermeiden. Ich sehe außerdem, dass du "Request.RefundTransactionRequest" erzeugst, aber nirgendwo freigibst. Ist es ein Interfaced-Typ mit Refcounting? Falls nein: Diesen MUSST du natürlich auch wieder freigeben, es reicht nicht, nur das Mutterobjekt freizugeben.
Hast du schon mal mit Delphi und SOAP bzw. mit Quelltext gearbeitet, der per Import einer WSDL-Datei in die Delphi-IDE zu einer Delphi-Unit umgewandelt wurde?
Eher nicht, oder?

Die Typen fallen so aus dem Quelltextgenerator raus. Klar kann man die umbenennen oder Aliase mit T dazuschreiben, aber wozu der Aufwand?
Die Freigabe von RefundTransactionRequest geschieht mit ziemlicher Sicherheit im Destroy von Request.
  Mit Zitat antworten Zitat
Dennis07

Registriert seit: 19. Sep 2011
Ort: Deutschland
242 Beiträge
 
Delphi XE5 Professional
 
#7

AW: PayPal Soap Anbindung

  Alt 13. Jun 2018, 12:54
Hast du schon mal mit Delphi und SOAP bzw. mit Quelltext gearbeitet, der per Import einer WSDL-Datei in die Delphi-IDE zu einer Delphi-Unit umgewandelt wurde?
Eher nicht, oder?
Nö. Hattest du geschrieben dass es ein automatisch generierter Source ist? Falls ja, hab ich es überlesen

Die Freigabe von RefundTransactionRequest geschieht mit ziemlicher Sicherheit im Destroy von Request.
"mit ziemlicher Sicherheit"? Das ist ja schön. Kannst du mal nachschauen, was im Konstruktor von "RefundTransactionRequest", beim Destruktor von "RefundTransactionReq", und in "CoUnInitialize" genau passiert?
Und selbst, wenn das so ist, wäre das eine weitere Fehlerquelle: Falls die Instanz (aus welchem Grund auch immer) der Parent class oder vom Childobjekt nicht erzeugt wurde, kriegst du 100% eine Fehlermeldung, im ersten Fall sogar noch ein Memory-Leak, da du ja das Objekt bereits erzeugt hast, was nun aber nicht zugewiesen werden kann.
Dennis

Geändert von Dennis07 (13. Jun 2018 um 13:00 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
1.808 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#8

AW: PayPal Soap Anbindung

  Alt 13. Jun 2018, 14:27
Hast du schon mal mit Delphi und SOAP bzw. mit Quelltext gearbeitet, der per Import einer WSDL-Datei in die Delphi-IDE zu einer Delphi-Unit umgewandelt wurde?
Eher nicht, oder?
Nö. Hattest du geschrieben dass es ein automatisch generierter Source ist? Falls ja, hab ich es überlesen

Die Freigabe von RefundTransactionRequest geschieht mit ziemlicher Sicherheit im Destroy von Request.
"mit ziemlicher Sicherheit"? Das ist ja schön. Kannst du mal nachschauen, was im Konstruktor von "RefundTransactionRequest", beim Destruktor von "RefundTransactionReq", und in "CoUnInitialize" genau passiert?
Und selbst, wenn das so ist, wäre das eine weitere Fehlerquelle: Falls die Instanz (aus welchem Grund auch immer) der Parent class oder vom Childobjekt nicht erzeugt wurde, kriegst du 100% eine Fehlermeldung, im ersten Fall sogar noch ein Memory-Leak, da du ja das Objekt bereits erzeugt hast, was nun aber nicht zugewiesen werden kann.

Wenn du schon drei Jahre alte Threads ausgräbst - warum das Leute immer wieder machen entzieht sich meinem Verständnis - dann wäre es gut, wenn du
a) den ganzen Thread liest (man beachte hierbei die ersten drei Zeilen des Eröffnungsposts nach der Begrüßung von Harry29) und
b) Erfahrung mit den Dingen hast, über die gesprochen wird.

Es gilt die alte Regel: Wenn keine Erfahrung vorliegt -> nicht dazu posten!
  Mit Zitat antworten Zitat
Dennis07

Registriert seit: 19. Sep 2011
Ort: Deutschland
242 Beiträge
 
Delphi XE5 Professional
 
#9

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
 
#10

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
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 23:46 Uhr.
Powered by vBulletin® Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2018 by Daniel R. Wolf