Erfassen Sie Ihre Fortschritte
Trailhead-Startseite
Trailhead-Startseite

Apex-SOAP-Callouts

Lernziele

Nachdem Sie dieses Modul abgeschlossen haben, sind Sie in der Lage, die folgenden Aufgaben auszuführen:
  • Generieren von Apex-Klassen mithilfe von WSDL2Apex
  • Ausführen eines Callouts zum Senden von Daten an einen externen Dienst mithilfe von SOAP
  • Testen von Callouts mithilfe simulierter Callouts

Generieren von Apex-Code mit WSDL2Apex

Neben REST-Callouts kann Apex mithilfe von XML auch Callouts an SOAP-Webservices richten. Das Arbeiten mit SOAP kann eine unangenehme (aber notwendige) Erfahrung sein. Zum Glück haben wir Tools, die den Prozess erleichtern.

WSDL2Apex generiert Apex-Klassen automatisch aus einem WSDL-Dokument. Sie laden die WSDL-Datei des Webservices herunter, laden dann die WSDL-Datei hoch, woraufhin WSDL2Apex die Apex-Klassen für Sie erstellt. Die Apex-Klassen konstruieren die SOAP XML, übertragen die Daten und analysieren die Antwort-XML in Apex-Objekte. Anstatt die Logik zum Konstruieren und Analysieren der XML der Webservicenachrichten zu entwickeln, lassen Sie die von WSDL2Apex generierten Apex-Klassen all diesen Verarbeitungsaufwand intern übernehmen. Wenn Sie mit WSDL2Java oder dem Importieren einer WSDL-Datei als Webverweis in .NET vertraut sind, ist diese Funktionalität mit WSDL2Apex vergleichbar. Gern geschehen.

Hinweis

Hinweis

Verwenden Sie zur Realisierung von Integrationslösungen nach Möglichkeit "Ausgehende Nachrichten". Verwenden Sie Callouts an Drittanbieter-Webservices nur im Bedarfsfall.

Bei diesem Beispiel verwenden wir einen einfachen Webservice mit einem Rechner zum Addieren zweier Zahlen. Dieser bahnbrechende Service ist der letzte Schrei! Zunächst müssen wir die WSDL-Datei herunterladen, um die Apex-Klassen zu generieren. Klicken Sie auf diesen Link und laden Sie die Datei calculator.xml auf Ihren Computer herunter. Merken Sie sich den Speicherort der Datei, da Sie sie im nächsten Schritt benötigen.

Erstellen einer Apex-Klasse aus der WSDL

  1. Geben Sie unter "Setup" im Feld Schnellsuche den Text Apex-Klassen ein und wählen Sie dann Apex-Klassen aus.
  2. Klicken Sie auf Aus WSDL generieren.
  3. Klicken Sie auf Datei auswählen und wählen Sie die heruntergeladene Datei calculator.xml aus.
  4. Klicken Sie auf WSDL analysieren. Die Anwendung generiert einen Standardklassennamen für die einzelnen Namespaces im WSDL-Dokument und meldet etwaige Fehler.

    In diesem Beispiel wird der Standardklassennamen verwendet. Doch in der Praxis wird ausdrücklich empfohlen, die Standardnamen zu ändern, um das Arbeiten mit ihnen zu erleichtern und Ihren Code intuitiver zu gestalten.

    Doch lassen Sie uns zunächst ehrlich über den WSDL-Parser sprechen. Die WSDL2Apex-Analyse ist notorisch unbeständig. Der Analyseprozess kann aus mehreren Gründen fehlschlagen, z. B. aufgrund eines nicht unterstützten Typs, mehrerer Bindungen oder unbekannter Elemente. Leider könnten Sie gezwungen sein, die Apex-Klassen manuell zu programmieren, die den Webservice aufrufen oder HTTP verwenden.

  5. Klicken Sie auf Apex-Code generieren. Auf der letzten Seite des Assistenten werden die generierten Klassen sowie etwaige Fehler angezeigt. Die Seite enthält darüber hinaus einen Link zum Anzeigen des erfolgreich erstellten Codes.

Die generierten Apex-Klassen enthalten Stub- und Typenklassen zum Aufrufen des Drittanbieter-Webservice, für den das WSDL-Dokument steht. Diese Klassen ermöglichen den Aufruf des externen Webservice aus Apex. Für jede generierte Klasse wird eine zweite Klasse mit demselben Namen und mit dem Präfix Async erstellt. Die Klasse calculatorServices ist für synchrone Callouts. Die Klasse AsyncCalculatorServices ist für asynchrone Callouts.

Ausführen des Callouts

Voraussetzungen

Ehe Sie dieses Beispiel ausführen, müssen Sie den Endpunkt-URL des Webservice-Callouts, https://th-apex-soap-service.herokuapp.com, anhand der Schritte im Abschnitt Autorisieren von Endpunktadressen autorisieren.

Nun können Sie den Callout ausführen und prüfen, ob die beiden Zahlen ordnungsgemäß addiert werden. Halten Sie einen Rechner bereit, um die Ergebnisse zu prüfen.

  1. Klicken Sie auf das Setup-Zahnradsymbol (Setup-Zahnradsymbol) und wählen Sie Entwicklerkonsole aus.
  2. Klicken Sie in der Entwicklerkonsole auf Debug | Open Execute Anonymous Window.
  3. Löschen Sie den gesamten vorhandenen Code und fügen Sie den folgenden Codeabschnitt ein.
    calculatorServices.CalculatorImplPort calculator = new  calculatorServices.CalculatorImplPort();
    Double x = 1.0;
    Double y = 2.0;
    Double result = calculator.doAdd(x,y);
    System.debug(result);
  4. Wählen Sie Open Log aus und klicken Sie auf Execute.
  5. Klicken Sie nach Öffnen des Debug-Protokolls auf Debug Only, um die Ausgabe der System.debug-Anweisungen anzuzeigen. Das Protokoll sollte 3.0 anzeigen.

Testen von Webservice-Callouts

Als erfahrene Apex-Entwickler wissen Sie, dass zum Bereitstellen oder Packen von Apex-Code mindestens 75 % dieses Codes von Tests abgedeckt sein müssen. Diese Abdeckung schließt unsere von WSDL2Apex erstellten Klassen ein. Sie haben vielleicht schon zuvor davon gehört, dass Testmethoden keine Webservice-Callouts unterstützen, sodass Tests, die Webservice-Callouts durchführen, fehlschlagen. Es ist also etwas Arbeit erforderlich. Zum Verhindern des Fehlschlagens von Tests und Steigern der Codeabdeckung bietet Apex die integrierte WebServiceMock-Schnittstelle und die Test.setMock-Methode. Sie können mithilfe dieser Schnittstelle in einem Test simulierte Antworten empfangen und so für die erforderliche Testabdeckung sorgen.

Angeben einer simulierten Antwort für Callouts

Wenn Sie eine Apex-Klasse aus einer WSDL-Datei erstellen, rufen die Methoden in der automatisch generierten Klasse WebServiceCallout.invoke auf, wodurch der Callout an den externen Service erfolgt. Beim Testen dieser Methoden können Sie die Apex-Laufzeit anweisen, eine simulierte Antwort zu generieren, wenn WebServiceCallout.invoke aufgerufen wird. Implementieren Sie hierzu die WebServiceMock-Schnittstelle und geben Sie eine simulierte Antwort an, die von der testenden Laufzeit gesendet werden soll.

Weisen Sie die Apex-Laufzeit an, diese simulierte Antwort zu senden, indem in Ihrer Testmethode Test.setMock aufgerufen wird. Übergeben Sie für das erste Argument WebServiceMock.class. Übergeben Sie für das zweite Argument eine neue Instanz Ihrer WebServiceMock-Schnittstellenimplementierung.

Test.setMock(WebServiceMock.class, new MyWebServiceMockImpl());

Da gibt es viel zu begreifen, weshalb wir uns den Code eines vollständigen Beispiels ansehen möchten. Bei diesem Beispiel erstellen Sie die Klasse, die den Callout ausführt, eine simulierte Implementierung für Tests und die Testklasse selbst.

  1. Klicken Sie in der Entwicklerkonsole auf File | New | Apex Class.
  2. Geben Sie als Klassennamen AwesomeCalculator ein und klicken Sie auf OK.
  3. Ersetzen Sie automatisch generierten Code durch die folgende Klassendefinition.
    public class AwesomeCalculator {
        public static Double add(Double x, Double y) {
            calculatorServices.CalculatorImplPort calculator = 
                new calculatorServices.CalculatorImplPort();
            return calculator.doAdd(x,y);
        }
    }
  4. Drücken Sie STRG+S, um zu speichern.

    Erstellen Sie Ihre simulierte Implementierung, um den Callout während der Tests zu simulieren. Ihre Implementierung von WebServiceMock ruft die doInvoke-Methode auf, die die Antwort zurückgibt, die Sie für Tests angeben. Der Großteil dieses Codes besteht aus Bausteinen. Der schwierigste Teil dieser Übung ist das Herausfinden, wie der Webservice eine Antwort zurückgibt, damit Sie einen Wert simulieren können.

  5. Klicken Sie in der Entwicklerkonsole auf File | New | Apex Class.
  6. Geben Sie als Klassennamen CalculatorCalloutMock ein und klicken Sie auf OK.
  7. Ersetzen Sie den automatisch generierten Code durch die folgende Klassendefinition.
    @isTest
    global class CalculatorCalloutMock implements WebServiceMock {
       global void doInvoke(
               Object stub,
               Object request,
               Map<String, Object> response,
               String endpoint,
               String soapAction,
               String requestName,
               String responseNS,
               String responseName,
               String responseType) {
            // start - specify the response you want to send
            calculatorServices.doAddResponse response_x = 
                new calculatorServices.doAddResponse();
            response_x.return_x = 3.0;
            // end
            response.put('response_x', response_x); 
       }
    }
  8. Drücken Sie STRG+S, um zu speichern.

    Schließlich muss Ihre Testmethode die Apex-Laufzeit anweisen, die simulierte Antwort zu senden, indem Test.setMock aufgerufen wird, bevor der Callout an die AwesomeCalculator-Klasse erfolgt. Wie bei anderen Testmethoden bestätigen wir, dass das richtige Ergebnis aus unserer simulierten Antwort empfangen wurde.

  9. Klicken Sie in der Entwicklerkonsole auf File | New | Apex Class.
  10. Geben Sie als Klassennamen AwesomeCalculatorTest ein und klicken Sie auf OK.
  11. Ersetzen Sie den automatisch generierten Code durch die folgende Klassendefinition.
    @isTest
    private class AwesomeCalculatorTest {
        @isTest static void testCallout() {              
            // This causes a fake response to be generated
            Test.setMock(WebServiceMock.class, new CalculatorCalloutMock());
            // Call the method that invokes a callout
            Double x = 1.0;
            Double y = 2.0;
            Double result = AwesomeCalculator.add(x, y);
            // Verify that a fake result is returned
            System.assertEquals(3.0, result); 
        }
    }
  12. Drücken Sie STRG+S, um zu speichern.
  13. Um diesen Test auszuführen, klicken Sie auf Test | Run All.

Für die AwesomeCalculator-Klasse sollte nun eine Codeabdeckung von 100 % angezeigt werden!

Ressourcen

Hinweis

Hinweis

Nicht vergessen: Dieses Modul bezieht sich auf Salesforce Classic. Wenn Sie Ihre Übungs-Organisation starten, wechseln Sie zu Salesforce Classic, um diese Aufgabe abzuschließen.