+ Start a Discussion
Mohith RamMohith Ram 

Hitting an error : Attempt to de-reference a null object - Need help - Newbie coding

I am trying to send SMS via Marketing Cloud APIs from clicking a custom list button on contact and getting error. Could you please help what is wrong in my code. 
Apex Controller:
Error

public class selectDefaulterSMS{
    @TestVisible
    private String smsSentVal;
    private static String className = selectDefaulterSMS.Class.getName();
    public Boolean unableToSendsms { get; private set; }
    private final Contact contactRecord;
    private transient String mobileWithCountryCode;
    
    public selectDefaulterSMS(ApexPages.StandardController controller) {
        contactRecord = (Contact)controller.getRecord();
    }
    public selectDefaulterSMS() {
    }
    
    public selectDefaulterSMS(ApexPages.StandardSetController controller) {
    }
    
    //Our collection of the class/wrapper objects cContact 
    public List<cContact> contactList {get; set;}
    //This method uses a simple SOQL query to return a List of Contacts
    public List<cContact> getContacts() {
        if(contactList == null) {
            contactList = new List<cContact>();
            for(Contact c: [select Id, Name, Email, Phone, MobilePhone, Default_SMS_Sent__c,Status__c from Contact limit 10]) {
                // As each contact is processed we create a new cContact object and add it to the contactList
                contactList.add(new cContact(c));
                
            }
        }
        return contactList;
    }
    
    public PageReference processSelected() {
        
        //We create a new list of Contacts that we be populated only with Contacts if they are selected
        List<Contact> selectedContacts = new List<Contact>();
        
        //We will cycle through our list of cContacts and will check to see if the selected property is set to true, if it is we add the Contact to the selectedContacts list
        for(cContact cCon: getContacts()) {
            if(cCon.selected == true) {
                selectedContacts.add(cCon.con);
            }
        }
        
        // Now we have our list of selected contacts and can perform any type of logic we want, sending emails, updating a field on the Contact, etc
        System.debug('+++++++ These are the selected Contacts... +++++++');
        for(Contact con: selectedContacts) {
            system.debug(con);
            /**********************/
            List<Log__c> errorLogs = new List<Log__c>();
            /*********** SendSMS API Call ************/
            // 1. Get Access token
            String accessToken = obtainAccessToken(errorLogs);
            
            if( accessToken != null) 
            {
                // 2.Make Send SMS API call
                if(sendSMSViaAPI(accessToken, smsSentVal, errorLogs) != 'success')
                {
                    // Display unable to verify message
                    unableToSendsms = true;
                }
            }
            else{
                // Display unable to verify message
                unableToSendsms = true;
            }        
            
            ///// Create Logs for Errors
            if(!errorLogs.isEmpty()) {
                try{
                    insert errorLogs;
                }catch(Exception ex)
                {
                    System.debug('Exception :' + ex.getMessage() + ' Stacktrace :' + ex.getStackTraceString());
                }
            }
            
            //smsDisabled = false;  
            //verified = false;   
            
            /**********************/
        }
        contactList=null; // we need this line if we performed a write operation  because getContacts gets a fresh list now
        return null;
    }
    
    // This is our wrapper/container class. A container class is a class, a data structure, or an abstract data type whose instances are collections of other objects. In this example a wrapper class contains both the standard salesforce object Contact and a Boolean value
    public class cContact {
        public Contact con {get; set;}
        public Boolean selected {get; set;}
        
        //This is the contructor method. When we create a new cContact object we pass a Contact that is set to the con property. We also set the selected value to false
        public cContact(Contact c) {
            con = c;
            selected = false;
        }
    }
    //methods for API calls
    private String obtainAccessToken(List<Log__c> errorLogs)
    {
        String accessToken = (cache.Org.get('MCAccessToken')!= null) ? (String) cache.Org.get('MCAccessToken') : null;  
        Integer expiresSeconds;     
        
        if(accessToken == null)
        {
            String accessEndpointURL = Label.SMSAccessTokenEndpoint;
            
            HttpRequest accessReq = new HttpRequest();
            Http accesshttp = new Http();
            accessReq.setEndpoint(accessEndpointURL);
            accessReq.setMethod('POST');
            
            accessReq.setBody('{  "clientId": "'+ Label.MarketingCloudClientId + '" ,"clientSecret": "' + Label.MarketingCloudClientSecret + '" }' );         
            accessReq.setHeader('Content-Type' , 'application/json');
            
            HTTPResponse accessRes;
            String accessResponseBody;      
            
            try{             
                accessRes = accesshttp.send(accessReq); 
                accessResponseBody = accessRes.getBody(); 
                
                System.debug('accessResponseBody :' + accessResponseBody); 
            }catch(Exception ex){
                System.debug('Exception :' +  ex);
                errorLogs.add(LoggerUtility.createLog(className, 'sendSMS:obtainAccessToken', ex, 'Message :' + ex.getMessage() + ' Cause :' + ex.getCause() , UserInfo.getUserId()));
            }
            
            if(accessRes != null && accessRes.getStatusCode() == 200)
            {
                JSONParser parser = JSON.createParser(accessResponseBody);
                parser.nextToken();
                parser.nextValue();
                accessToken = parser.getText();
                
                parser.nextToken();
                parser.nextValue();
                expiresSeconds = parser.getIntegerValue();
                
                cache.Org.put('MCAccessToken', accessToken, expiresSeconds - 20, cache.Visibility.ALL, false);
                return accessToken;
            }else
            {
                System.debug('Exception :' );
                errorLogs.add(LoggerUtility.createLog(className, 'sendSMS:obtainAccessToken', null, 'accessResponseBody :' + accessResponseBody, UserInfo.getUserId()));
            }
            
            return null;
        }  
        //Cached access token not expired        
        return accessToken;         
        
    }
    
    // Send SMS API call
    private String sendSMSViaAPI(String accessToken, String smsSentVal,List<Log__c> errorLogs){
        
        String endpointURL = Label.SMSSendEndpoint; // This is for the first and only supported country which was AU
        String mobileNumber = contactRecord.MobilePhone.startswith('0') ? contactRecord.MobilePhone.substring(1) : contactRecord.MobilePhone;
        mobileNumber = mobileNumber.replaceAll(' ',''); // remove any spaces
        
        Map<String, Mobile_Country_Code__c> mobileCountryCodesMap = Mobile_Country_Code__c.getAll();
        
        Integer countryCode; String keyWordSuffix;
        Mobile_Country_Code__c ccode;
        
        if(mobileCountryCodesMap.containsKey(contactRecord.et4ae5__Mobile_Country_Code__c)) { 
            ccode = mobileCountryCodesMap.get(contactRecord.et4ae5__Mobile_Country_Code__c);
            
            countryCode =  (Integer)ccode.Numerical_Code__c;
            keyWordSuffix = ccode.Name;
        }  
        
        if(countryCode !=  null) {
            
            //SMS support has now been extended for few countries , each country uses it's own SFMC message Id i.e it's customised end point
            //For international numbers
            if(countryCode != 61 && ccode.Is_SMS_Supported__c){
                endpointURL = Label.SMSSendEndpoint_BaseUrl + ccode.MessageId__c + '/send';                         
            }
            
            mobileWithCountryCode = String.valueOf(countryCode) + mobileNumber;
            
            List<String> phoneNumber = new List<String>{ mobileWithCountryCode };
                System.debug('JSON.serialize(phoneNumber) :' + JSON.serialize(phoneNumber));
            
            Map<String, Object> objMap = new Map<String, Object>();         
            
            objMap.put('SendTime', '2018-10-10 20:01');
            objMap.put('messageText', 'Please verify your mobile number using the following code:'+ smsSentVal);
            objMap.put( 'Override', true);
            objMap.put('keyword',  (countryCode == 61) ? 'SYSTEM' : 'SYSTEM_' + keyWordSuffix);
            objMap.put( 'Resubscribe', true);
            objMap.put( 'Subscribe', true);
            objMap.put('mobileNumbers',phoneNumber);        
            
            String bodyMsg = JSON.serialize(objMap);
            
            System.debug('bodyMsg :' + bodyMsg);
            
            HttpRequest req = new HttpRequest();
            Http http = new Http();
            req.setEndpoint(endpointURL);
            req.setMethod('POST');
            
            req.setBody(bodyMsg);  
            req.setHeader('Authorization', 'Bearer '+ accessToken);
            req.setHeader('Content-Type' , 'application/json');
            
            HTTPResponse res;
            String responseBody;
            
            try{  
                res = http.send(req); 
                responseBody = res.getBody(); 
                System.debug('responseBody :' + responseBody);
            }catch(Exception ex){
                System.debug('Exception :' +  ex);
                errorLogs.add(LoggerUtility.createLog(className, 'sendSMS:sendSMSViaAPI', ex, 'Message :' + ex.getMessage() + ' Cause :' + ex.getCause() , UserInfo.getUserId()));
            }
            
            if(res != null && res.getStatusCode() == 202)
            {             
                return 'success';
            }
            else
            {
                errorLogs.add(LoggerUtility.createLog(className, 'sendSMS:sendSMSViaAPI', null, 'responseBody :' + responseBody, UserInfo.getUserId()));
            } 
            return 'failed';
        }
        
        return null;
        
    }
}
Visualforce Page:
<apex:page standardController="Contact"
    recordSetVar="Contact"
    extensions="selectDefaulterSMS"
    showHeader="true"
    sidebar="true"
    id="mucon"
>
    <apex:form id="muform">
        
        <apex:pageBlock title="SMS Defaulters Communication" mode="edit" id="mub1">
            <apex:pageMessages />
           <!-- <apex:pageBlockSection id="mus1">
                <apex:inputField value="{!contact.Default_SMS_Sent__c}" id="defaultSMS">
                    <apex:actionSupport event="onchange" rerender="muselectedlist"/>
                </apex:inputField>
            </apex:pageBlockSection> -->
            <apex:pageBlockButtons location="bottom" id="mubut">
                <apex:commandButton value="Send SMS" action="{!processSelected}" id="butsav"/>
                <apex:commandButton value="Cancel" action="{!cancel}" id="butcan"/>
            </apex:pageBlockButtons>

        <!-- get all the Ids for the contacts that needs to be sent with the SMS -->
        <apex:pageBlockTable value="{!contacts}" var="c" id="table">
                <apex:column >
                    <!-- This is our selected Boolean property in our wrapper class -->
                    <apex:inputCheckbox value="{!c.selected}"/>
                </apex:column>
                <!-- This is how we access the contact values within our cContact container/wrapper -->
                <apex:column value="{!c.con.Name}" />
                <apex:column value="{!c.con.MobilePhone}" />
                <apex:column value="{!c.con.Email}" />
                <apex:column value="{!c.con.Phone}" />
                <apex:column value="{!c.con.Default_SMS_Sent__c}" />
                <apex:column value="{!c.con.Status__c}" headerValue="Contact Status"/>
        </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:form>
</apex:page>
Nikhil SutharNikhil Suthar
Hello,
Attempt to de-reference a null object this error usually generates when it founds not initialized object and it consider it null.
Kindly initialize object with new keyword and then use it
Example: Contact con ;
con = new Contact();

Thanks