0

I am trying to find all the leads with email campaigns then make a list of the hashed email addresses for those leads for each of the leads owners. So Shays list would have every email address of the leads assigned to him. I am getting an error adding the first hash to the list.

Map<String, list<string>> listmaker = new Map<String, list<string>>(); 
    for(Lead lead : [select owner.firstname, email from lead where email !=null AND ID IN (select lead__c from email_campaign__c)]){
        list<string> recipients = new list<string>();
        string recipient;
        string lemail = lead.email;
        blob hashmail = blob.valueOf(lemail);
        recipient = EncodingUtil.base64Encode(hashmail);
        system.debug(recipient);
        system.debug('***NAME*** '+lead.owner.firstname);
        if(listmaker.containsKey(lead.owner.firstname)==FALSE){
            recipients.add(' ');
            recipients.add(recipient);
            listmaker.put(lead.owner.firstname, recipients);
        }
        if(listmaker.containsKey(lead.owner.firstname)==TRUE){
            recipients = listmaker.get(lead.owner.firstname);
            recipients.add(recipient);
            listmaker.put(lead.owner.firstname, recipients);
        }   
    }
    hashid_shay=listmaker.get('shay');
    hashid_austin=listmaker.get('austin');
    system.debug(hashid_shay); system.debug(hashid_austin);



   string json_payloads = json.serialize(hashid_shay);
   sendgridsettings__c sends = sendgridsettings__c.getInstance('shay');
   SendGridAPI.sendRequest(json_payloads, '/contactdb/lists/{' + sends.list_id__c + '}/recipients', 'POST');
   string json_payloada = json.serialize(hashid_austin);                                 
   sendgridsettings__c senda = sendgridsettings__c.getInstance('austin');
   SendGridAPI.sendRequest(json_payloada, '/contactdb/lists/{' + senda.list_id__c + '}/recipients', 'POST');
2
  • What error are you getting? – Eric Sep 19 '17 at 6:58
  • I updated the code, I am no longer getting any errors. However, it's returning a null json_payload a and s. I am not seeing my mistake... – Roger Morris Sep 19 '17 at 7:20
2

The original issue with your code was that you were delcaring recipients as a list/array of strings, but you did not initialize that variable before attempting to use it.

// This is a declaration only
String[] myStringList;

// If you were to debug this, or any other uninitialized variable, you would see that 
//   the value is null (until the variable is initialized).
system.debug(myStringList);

// If you try to use a variable before initializing it, you're liable to get a 
//   Null Pointer Exception.
// myStringList.add('test');

// Initialization generally refers to the first time you set a (non-null) value
//   for a variable.
myStringList = new String[];

// debugging now will result in an empty list, i.e. '[]'
system.debug(myStringList);

// You can declare and initialize on the same line
String[] myOtherStringList = new String[];

Your current (at time of writing) code takes care of that. I could suggest some improvements to your implementation though.

Map<String, list<string>> listmaker = new Map<String, list<string>>();

for(Lead lead : [select owner.firstname, email from lead where email !=null AND ID IN (select lead__c from email_campaign__c)]){
        list<string> recipients = new list<string>();
        string recipient;
        string lemail = lead.email;
        blob hashmail = blob.valueOf(lemail);
        recipient = EncodingUtil.base64Encode(hashmail);
        system.debug(recipient);
        system.debug('***NAME*** '+lead.owner.firstname);

        // if(value == true) can be replaced with simply if(value).
        // Likewise, if(value == false) can be replaced with if(!value).
        // The inside (the condition) of an if statement must be a boolean value.
        // true ==  true results in true, false == false results in true, and
        // !false (not false) results in true.
        /*if(!listmaker.containsKey(lead.owner.firstname)){
            recipients.add(' ');
            recipients.add(recipient);
            listmaker.put(lead.owner.firstname, recipients);
        }
        if(listmaker.containsKey(lead.owner.firstname)){
            recipients = listmaker.get(lead.owner.firstname);
            recipients.add(recipient);
            listmaker.put(lead.owner.firstname, recipients);
        }*/

        // Even with that simplification, I've commented those if statements out because
        //   we can simplify them further.
        // Since your if condition is a single term, and ends up testing (condition == true)
        //  and (condition == false), you could turn the second if() into an else.
        /*if(!listmaker.containsKey(lead.owner.firstname)){
            recipients.add(' ');
            recipients.add(recipient);
            listmaker.put(lead.owner.firstname, recipients);
        }else{
            recipients = listmaker.get(lead.owner.firstname);
            recipients.add(recipient);
            listmaker.put(lead.owner.firstname, recipients);
        }*/

        // We can still simplify further.
        // Within a single class, it's generally a good idea for your code to be DRY
        //   (Don't Repeat Yourself) rather than WET (Write Everything Twice)
        // I think this pattern results in the DRYest, least amount of typing generally
        //   required for populating a map.

        if(!listmaker.containsKey(lead.owner.firstname)){
            // Inside this if block, we know that we have not encountered this map key
            //   before.
            // Our only concern here is to make sure we store _something_ that we
            //   can work with after we exit this block.
            listmaker.put(lead.owner.firstname, new List<String>());
        }

        // Starting here, we are guaranteed to have a list to work with for the 
        //   current lead owner.
        // When we call .get() on the map, we're given a reference to the thing contained
        //   in the map.
        // That means that any changes we make to the thing we got from the map are
        //   automatically changed in the map too (no need to .put(key, newvalue))
        listmaker.get(lead.owner.firstname).add(recipient);


    }
    hashid_shay=listmaker.get('shay');
    hashid_austin=listmaker.get('austin');
    system.debug(hashid_shay); system.debug(hashid_austin);



   string json_payloads = json.serialize(hashid_shay);
   sendgridsettings__c sends = sendgridsettings__c.getInstance('shay');
   SendGridAPI.sendRequest(json_payloads, '/contactdb/lists/{' + sends.list_id__c + '}/recipients', 'POST');
   string json_payloada = json.serialize(hashid_austin);                                 
   sendgridsettings__c senda = sendgridsettings__c.getInstance('austin');
   SendGridAPI.sendRequest(json_payloada, '/contactdb/lists/{' + senda.list_id__c + '}/recipients', 'POST');

Your current (at time of writing) problem is that you're seeing empty payloads.

My only guess with the information that you've provided is that the keys of your map must not be 'shay' and 'austin'.

Map keys are case sensitive. You can verify that for yourself by running the following snippet via anonymous apex:

Map<String, String> testMap =  new Map<String, String>();
testMap.put('test', 'first test');
testMap.put('Test', 'second test');

system.debug(testMap);
// prints "USER_DEBUG [5]|DEBUG|{Test=second test, test=first test}"

I'd expect that your users' names in Salesforce are properly capitalized ('Shay', 'Austin'), meaning that the uncapitalized versions would not be in your map.

In any case, you would benefit from applying some discipline here. Mixing conventions leads to errors. Instead of having your users' names be capitalized, and your custom setting keys be all lowercase, I'd recommend altering your custom setting keys to match the conventions of your users' names. In reality, it doesn't matter which way you choose to do it (capitalize your custom setting keys, or turn all user names to lowercase), what matters is that you choose one convention and stick with it.

Once you have that in place, you can make the last portion of your code more general (so you won't have to go back and update your code when Shay leaves or when Chase joins your company/team). This is where Ajay's answer comes into play.

// Assuming the convention used for the custom setting and user names match, there's
//   no need to pre-fetch/hard-code data outside of a loop.
// Loop over the map keys
for(String username :listmaker.keySet()){
    String sendSetting = sendgridsettings__c.getInstance(username);

    // Storing parameters to a call as separate parameters can make things a 
    //   bit easier to read...but do incur a small amount of overhead.
    // I chose to serialize your payload data inline (as opposed to storing in
    //   a separate variable), but it really doesn't make any difference.
    // Use whatever you're more comfortable with (again, _be consistent_)
    SendGridAPI.sendRequest(json.serialize(listmaker.get(username)), '/contactdb/lists/{' + sendSetting.list_id__c + '}/recipients', 'POST');
}
1

To Iterate over a map you can iterate over keyset of map or values of the map

for(String listm :listmaker.keySet()){

}

To iterate over the list of the corresponding key value, you have to use another loop-

for(String listm :listmaker.keySet()){
    for(String stringObj : listmaker.get(listm)){

    }
}

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.