You need to sign in to do that
Don't have an account?

Converting Trigger to Batch Apex: Help needed to make the code work
If possible, could anyone please direct me towards the right direction? The second code (Batch Apex) is just not compiling. Currently the error is,
Error: Compile Error: Invalid type: updateContactOnEmailOptOutChangeScheduler at line 63 column 73
Original Trigger Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | trigger updateContactOnEmailOptOutChange on Contact (after update) {
Batch Apex
global class updateContactOnEmailOptOutChange implements Database.Batchable<sObject> for(Integer i=0; i<Trigger.new.size();i++)
|
This is complaining that the compiler can't find a class named updateContactOnEmailOptOutChangeScheduler. You haven't posted this class - does it exist?
Thanks for the reply Bob!
I was thinking about the other way in which this requirement could be solved.
Here's the trigger that would call batch apex when the HasOptedOutOfEmail has changed:
/**The trigger code where we check if the field HasOptedOutOfEmail has changed and if changed, implement batch apex to update all duplicate
contacts with the new HasOptedOutOfEmail value**/
trigger updateonEmailOptOutChange on Contact (after update) {
Map<string, Contact> contactEmailMap = new Map<String, Contact>();
Map<Id, Contact> contactIdMap = new Map<Id, Contact>();
// Build a Map with contacts to update. Only select the ones that have a different "Email Opt Out' value from the contact being updated.
for (integer i=0; i< Trigger.new.size();i++){
if(Trigger.old[i].HasOptedOutOfEmail != Trigger.new[i].HasOptedOutOfEmail){
contactEmailMap.put(Trigger.old[i].email, Trigger.new[i]);
contactIdMap.put(Trigger.old.id, Trigger.new[i]);
}
}
// Call the batch apex only if "Email Opt Out" (HasOptedOutOfEmail) field was updated.
if(contactIdMap.size() > 0){
Database.executeBatch(new HasOptedOutOfEmailBatch(contactIdMap));
}
}
And here's the batch apex that will do the job:
global class HasOptedOutOfEmailBatch implements Database.Batchable<sObject>
{
// map of contactid and contact
Map<Id, Contact> ContactIdMap = new Map<Id, Contact> ();
Map<String,Contact> contactEmailMap = new Map<String,Contact>();
List<Contact> duplicateContacts = new List<Contact>();
global HasOptedOutOfEmailBatch(Map<Id,Contact> ContactId, Map<String,Contact> contactEmail)
{
ContactIdMap = ContactId;
ContactEmailMap =contactEmail;
}
global Database.QueryLocator start(Database.BatchableContext BC)
{
return Database.getQueryLocator([SELECT Id, Name, Email, HasOptedOutOfEmail FROM Contact
WHERE Email IN: contactEmailMap.KeySet()
AND Id NOT IN: contactIdMap.KeySet()]);
}
global void execute(Database.BatchableContext BC, List <Contact> dupContact)
{
for(integer i=0; i<dupContact.size();i++){
Contact contact = contactEmailMap.get(dupContact.Email); >>>>>> Line 24
If(dupContact.HasOptedOutOfEmail <> contact.HasOptedOutOfEmail){
dupContact.HasOptedOutOfEmail = contact.HasOptedOutOFEmail;
duplicateContacts.add(dupContact);
}
}
update duplicateContacts;
}
global void finish(Database.BatchableContext BC)
{
//Send an email to the User after the batch completes
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
String[] toAddresses = new String[] {'craigls@gmail.com'};
mail.setToAddresses(toAddresses);
mail.setSubject('Apex Batch Job of Email Opt Out field is done');
mail.setPlainTextBody('The Batch Apex Job processed');
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
}
}
Before I save the trigger, I must have the batch class ready. However, now I am getting the error 'Initial term of field expression must be a concrete SObject: LIST<Contact> at line 24 column 43'.
Again, the requirement is whenever a contact update happens, in the field of "Email Opt Out" (which is a checkbox), the duplicate contacts that have different 'Email Opt Out' value are also updated.
Thanks!!
In this line:
Trigger.old.id should be Trigger.old[i].id, I reckon.
Also, be wary when firing scheduled/batch apex from triggers. If a lot of users change the contact information in a short timeframe, you can end up breaching the limits which results in jobs being removed from the queue.
Now, I am having another issue. I just wrote a test class to see to see if the duplicate contacts are actually being updated or not. But it's showing an error.
Trigger:
contacts with the new HasOptedOutOfEmail value**/
trigger updateonEmailOptOutChange on Contact (after update) {
Map<string, Contact> contactEmail = new Map<String, Contact>();
Map<Id, Contact> contactId = new Map<Id, Contact>();
// Build a Map with contacts to update. Only select the ones that have a different "Email Opt Out' value from the contact being updated.
for (integer i=0; i< Trigger.new.size();i++){
if(Trigger.old[i].HasOptedOutOfEmail != Trigger.new[i].HasOptedOutOfEmail){
contactEmail.put(Trigger.old[i].email, Trigger.new[i]);
contactId.put(Trigger.old[i].id, Trigger.new[i]);
}
}
// Call the batch apex only if "Email Opt Out" (HasOptedOutOfEmail) field was updated.
if(contactId.size() > 0){
Database.executeBatch(new HasOptedOutOfEmailBatch(contactId,contactEmail));
}
}
Batch Apex
global class HasOptedOutOfEmailBatch implements Database.Batchable<sObject>
{
// map of contactid and contact
Map<Id, Contact> ContactIdMap = new Map<Id, Contact> ();
Map<String,Contact> contactEmailMap = new Map<String,Contact>();
List<Contact> duplicateContacts = new List<Contact>();
global HasOptedOutOfEmailBatch(Map<Id,Contact> ContactId, Map<String,Contact> contactEmail)
{
ContactIdMap = ContactId;
ContactEmailMap =contactEmail;
}
global Database.QueryLocator start(Database.BatchableContext BC)
{
return Database.getQueryLocator([SELECT Id, Name, Email, HasOptedOutOfEmail FROM Contact
WHERE Email IN: contactEmailMap.KeySet()
AND Id NOT IN: contactIdMap.KeySet()]);
}
global void execute(Database.BatchableContext BC, List <Contact> duplicateContacts)
{
// for(integer i=0; i<dupContact.size();i++){
for (Contact dupContact:[SELECT Id, Name, Email, HasOptedOutOfEmail FROM Contact
WHERE Email IN: contactEmailMap.KeySet()
AND Id NOT IN: contactIdMap.KeySet()]){
Contact contact = contactEmailMap.get(dupContact.Email);
If(dupContact.HasOptedOutOfEmail <> contact.HasOptedOutOfEmail){
dupContact.HasOptedOutOfEmail = contact.HasOptedOutOFEmail;
duplicateContacts.add(dupContact);
}
}
update duplicateContacts;
}
global void finish(Database.BatchableContext BC)
{
//Send an email to the User after the batch completes
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
String[] toAddresses = new String[] {'craigls@gmail.com'};
mail.setToAddresses(toAddresses);
mail.setSubject('Apex Batch Job of Email Opt Out field is done');
mail.setPlainTextBody('The Batch Apex Job processed');
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
}
}
TEST CLASS
@isTest(SeeAllData =true)
private class updateonEmailOptOutChangeTest
{
static testMethod void updateonEmailOptOutChangeTest()
{
Contact ConObj1=new Contact();
ConObj1.Email='TestUser1@gmail.com';
//conObj1.Id='0038000001ANnQrISH';
ConObj1.HasOptedOutOfEmail = False;
ConObj1.LastName = 'Mathema' ;
insert conObj1;
Contact ConObj2 = new Contact();
ConObj2.Email = 'TestUser1@gmail.com';
//conObj1.Id='D00000000000000';
ConObj2.HasOptedOutOfEmail =False;
ConObj2.LastName='Mathema' ;
insert ConObj2;
conObj1.HasOptedOutOfEmail= True;
update ConObj1;
System.assert(ConObj1.HasOptedOutOfEmail == ConObj2.HasOptedOutOfEmail);
}
}