0

I've just written my first batch which should change a contact's email from [email protected] to [email protected]

global class changeEmailAddressesToExampleInSandbox implements Database.Batchable<sObject> {

List<Contact> contactsEmails;
String tempEmail;
String newEmailDomain;
String query;
Integer totalNumOfContacts;
Integer counter;


global changeEmailAddressesToExampleInSandbox() {
    newEmailDomain = '@example.com';
    contactsEmails = new List<Contact>();
    query = 'SELECT email FROM Contact';
    tempEmail=' ';
    totalNumOfContacts=[select count() from contact];
    counter=0;

}
global Database.QueryLocator start(Database.BatchableContext BC) {
    return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<Contact> scope) { //changed Sobject to Contact
    for(Contact con : scope){
        tempEmail=con.Email;
        if(!tempEmail.contains('@example.com')){
            tempEmail = tempEmail.split('@')[0];
            tempEmail+= newEmailDomain;
            counter++;
        }
        contactsEmails.add(con);
    }
}
global void finish(Database.BatchableContext BC) {
    try{
        update contactsEmails;
    }
    catch(Exception e){system.debug(e);}

    Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
    message.toAddresses = new String[] { '[email protected]'};
    message.optOutPolicy = 'FILTER';
    message.subject = 'Email From New Sandbox';
    message.plainTextBody = 'All contacts\' emails have been modified succesfully ' +'\n'+'The total number of contacts in the Sandbox is '+totalNumOfContacts+'\n'+counter+' contacts were updated';
    Messaging.SingleEmailMessage[] messages =   new List<Messaging.SingleEmailMessage> {message};
    Messaging.SendEmailResult[] results = Messaging.sendEmail(messages);

    if (results[0].success) {
        System.debug('The email was sent successfully.');
        } else {
            System.debug('The email failed to send: ' + results[0].errors[0].message);
        }
    }
}

When I try to execute the following code on the Developer Console nothing happens, emails stay the same.

changeEmailAddressesToExampleInSandbox b = new changeEmailAddressesToExampleInSandbox();
Database.executeBatch(b);
4
  • 1
    Id batchJobId = Database.executeBatch(new changeEmailAddressesToExampleInSandbox(), 200);
    – TSmith
    Commented Dec 13, 2016 at 14:07
  • @TSmith tried it and got the same error
    – Json
    Commented Dec 13, 2016 at 14:08
  • 1
    Compiled this class in my dev environemnt and ran batch execution from dev console. Do you have anything else in your environment like changeEmailAddressesToExampleInSandbox that may be causing conflict?
    – TSmith
    Commented Dec 13, 2016 at 14:31
  • @TSmith it's compiling! but it isn't working.
    – Json
    Commented Dec 13, 2016 at 14:46

1 Answer 1

2

If this batchable has been written in an org that has a namespace defined from the developer console you will have to use the namespace prefix i.e.:

Database.executeBatch(new prefix.changeEmailAddressesToExampleInSandbox());

If it isn't then global isn't really needed; not sure what your immediate problem is.

To avoid governor limits you should change the code to something more like this:

public class changeEmailAddressesToExampleInSandbox implements
        Database.Batchable<sObject>, Database.Stateful {

    private Integer total = 0;
    private Integer modified = 0;

    public Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator([SELECT email FROM Contact]);
    }

    public void execute(Database.BatchableContext bc, List<Contact> scope) {
        String newEmailDomain = '@example.com';

        List<Contact> updates = new List<Contact>();
        for (Contact con : scope){
            String tempEmail = con.Email;
            if(!String.isEmpty(tempEmail) && !tempEmail.contains('@example.com')){
                tempEmail = tempEmail.split('@')[0];
                tempEmail += newEmailDomain;
                con.Email = tempEmail;
                updates.add(con);
            }
        }
        update updates;

        modified += updates.size();
        total += scope.size();
    }
    public void finish(Database.BatchableContext bc) {

        ...
        message.plainTextBody = ''
                + 'All contacts\' emails have been modified successfully ' +'\n'
                + 'The total number of contacts in the Sandbox is '
                + total + '\n'
                + modified +' contacts were updated'
                ;
        ....
    }
}

This updates the Contact in groups to avoid the DML governor limit and never tries to count the Contacts in one go as that can hit the number of records retrieved governor limit. For class field values to be preserved across the various methods, you must add the Database.Stateful marker.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .