2

As a follow up to my previous post: REST API calls to 3rd Party (Pardot), multiple @future callouts

There are two responses I expect back when I attempt this Web Service callout to Pardot:

1) Success

<?xml version="1.0" encoding="UTF-8"?> <rsp stat="ok" version="1.0"> <api_key>6d800bfaab63274b1b908dacd8544936</api_key> </rsp>

2) Failure:

<?xml version="1.0" encoding="UTF-8"?> <rsp stat="fail" version="1.0"> <err code="15">Login failed</err> </rsp>

The problem is if I attempt to parse the success and it was a failed attempt then I get a debug status error of "Attempt to de-reference a null object" So I'm wondering if there is a way to do a try() or if() statement that will look for fail or success and then return the other, something like this in theory:

/* Try to send the request */
try {
    response = http.send(request);
    System.debug('::RESPONSE::'+response.getBody());

    /* Setup Document for parsing */
    Dom.Document doc = response.getBodyDocument();
    Dom.XMLNode results = doc.getRootElement();

//=======================================
  NOTE: Currently if this next line fails
        then everything stops so the if 
        statement never happens.
===========================================//

    String api_key = results.getChildElement('api_key', null).getText();
    if( api_key != '' ){
        return api_key;
    } else {
        System.debug('::API REQUEST ERROR:: '+results.getChildElement('err', null).getText());
        return '';
    }
} catch(System.CalloutException e) {
    System.debug('ERROR: '+ e);
    return '';
}
4

The previous answer I gave you assumed success, but for robustness, you can certainly iterate through all expected values. For example:

Dom.Document doc = new Dom.Document();
doc.load(res.getBody());
Dom.XmlNode root = doc.getRootElement();
if(root.getName()=='rsp') {
    for(Dom.XmlNode node1: root.getChildElements()) {
        if(node1.getName()=='err') {
            // handle error condition
        }
        if(node1.getName()=='api_key') {
           // store api_key for use
        }
    }
}

If you reach the end without an API key or error, that just means that you ran out of nodes, and should probably just throw some general exception, instead.

See the XmlNode Class documentation for more assistance on using this built-in library.

  • For completeness can you update your code to include the try() response and the exception you're referring to. Thanks trying this out now – Xtremefaith Oct 22 '14 at 17:33
  • @Xtremefaith This code won't crash by itself-- the idea would be that you may want to report the error to the calling function, so the try-catch would be higher up the call stack. For example, getChildElements() returns an empty array if there are no elements, and an empty loop never executes its body. – sfdcfox Oct 22 '14 at 17:38
  • very strange when compiling for deploy I get this: Error: Invalid type: XmlNode @ XmlNode root = doc.getRootElement(); and the response shows the body as expected so not sure the problem – Xtremefaith Oct 22 '14 at 18:11
  • I forgot XmlNode is in the Doc namespace. See modified answer. – sfdcfox Oct 22 '14 at 18:36
  • Awesome that worked great. To store the API_Key now would I just use this: String api_key = root.getChildElement('api_key', null).getText(); ? – Xtremefaith Oct 22 '14 at 18:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.