function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Rahavan Arumugam AlameluRahavan Arumugam Alamelu 

ExecuteBatchApex

Am  unable to execute the apex batch class. Getting error as "Method does not exist or incorrect signature: void executeBatch(UserDeactivation_batchable) from the type Database"

Apex batchable class:

global class UserDeactivation_Batchable implements Database.Batchable<sObject>
{
    Batch_Job_Settings__c batchJobSettings = Batch_Job_Settings__c.getInstance('Batch Job Settings');
    Decimal DAYS_IN_THE_PAST = batchJobSettings.UD_Days_After_Last_Modified__c;  
    String ERROR_EMAIL= batchJobSettings.batchJobSettings;
    String PROFILE_NAME = batchJobSettings.UD_Profile_Name__c;
    String INACTIVE_TEXT = batchJobSettings.UD_Inactive_Text__c;
    Date thresholdDate = System.today().addDays(-DAYS_IN_THE_PAST.intValue());
 Integer year = thresholdDate.year();
 String month;
    if (thresholdDate.month() < 10)  {month = '0' + thresholdDate.month();}
  
    else
        {
   month = thresholdDate.month().format();
  }
  String day;
  if (thresholdDate.day() < 10) {
   day = '0' + thresholdDate.day();
  } else {
   day = thresholdDate.day().format();
  }
  String thresholdDateString = year +'-'+ month +'-'+ day + 'T23:59:59Z';

query='SELECT Id, isActive, ProfileId, Email, UserName, CommunityNickname, FederationIdentifier, Federation_Id_2__c User WHERE Profile.Name = \'' + PROFILE_NAME + '\ AND isActive = true AND LastModifiedDate <= ' + thresholdDateString;
global Database.QueryLocator start(Database.BatchableContext BC)
{
    System.debug(System.LoggingLevel.DEBUG, '##DEBUG: START - query: ' + query);
    return Database.getQueryLocator(query);
}
    global void execute(Database.BatchableContext BC, List<User> users)
    {
        System.debug(System.LoggingLevel.DEBUG, '##DEBUG: execute begin. Number of users to process: ' + users.size());
        for (User inactiveProfileUser : users)
        {
            inactiveProfileUser.isActive=false;
            inactiveProfileUser.Username=INACTIVE_TEXT + inactiveProfileUser.UserName;
        }
        System.debug(System.LoggingLevel.DEBUG,'##DEBUG: Database Update List of Users: ' + users.size());
        List<Database.SaveResult> userSaveResults=Database.update(users, false);
        System.debug(System.LoggingLevel.DEBUG, 'Loop through list of saved results'+ userSaveResults.size());
        List<String> userDeactivationUpdateErrors =new List<String>();
        for(Integer counter=0;counter<userSaveResults.size();counter++)
        {
            Database.SaveResult userSaveResult=userSaveResults[counter];
            if(!userSaveResult.isSuccess())
                System.debug(System.LoggingLevel.DEBUG,'##DEBUG: Errors exist for this userSave: ' + userSaveResult);
            for(Database.Error error:userSaveResult.getErrors())
            {
    String errorMessageAndCode = 'User Deactivation Errors for User: ' + users[counter].Id + ': ';
    errorMessageAndCode += error.getStatusCode() +':'+ error.getMessage();
    userDeactivationUpdateErrors.add(errorMessageAndCode);

            }
        }
       
    if(!userDeactivationUpdateErrors.isEmpty())
    {
        System.debug('##DEBUG: userDeactivationUpdateErrors exist: ' + userDeactivationUpdateErrors);
        Messaging.SingleEmailmessage mail=new Messaging.SingleEmailMessage();
        mail.setToAddresses(new String[] {ERROR_EMAIL});
        mail.setSubject('User Deactivation Batch Errors:' +System.now()+':Batch Job Id:' + BC.getJobId());
        String messageHtmlBody='<h2>User Deactivation Errors</h2> <br/>';
        for (String userDeactivationUpdateError:userDeactivationUpdateErrors)
        {
            messageHtmlBody+= userDeactivationUpdateError + '<br/>'
        }
        mail.setHtmlBody('<p>The User Deactivation batch Apex job ' + BC.getJobId() +' had the following errors:</p>' + messageHtmlBody);
        Messaging.SingleEmailMessage[mail];
       
    }
    }
    global void finish(Database.BatchableContext BC) {}
}

Kindly advise.

Thanks
Rahavan

 
PawanKumarPawanKumar
you can execute by calling below line.

Database.executeBatch(new UserDeactivation_Batchable());

But i do not think the class is proper. You can try running below code.

global class UserDeactivation_Batchable implements Database.Batchable < sObject > {
 global String query = '';
 List < String > userDeactivationUpdateErrors = new List < String > ();

 // constructor
 pubic UserDeactivation_Batchable() {

  Batch_Job_Settings__c batchJobSettings = Batch_Job_Settings__c.getInstance('Batch Job Settings');
  Decimal DAYS_IN_THE_PAST = batchJobSettings.UD_Days_After_Last_Modified__c;

  // below line is wrong batchJobSettings.batchJobSettings
  String ERROR_EMAIL = batchJobSettings.batchJobSettings;

  String PROFILE_NAME = batchJobSettings.UD_Profile_Name__c;
  String INACTIVE_TEXT = batchJobSettings.UD_Inactive_Text__c;
  Date thresholdDate = System.today().addDays(-DAYS_IN_THE_PAST.intValue());
  Integer year = thresholdDate.year();
  String month;
  if (thresholdDate.month() < 10) {
   month = '0' + thresholdDate.month();
  } else {
   month = thresholdDate.month().format();
  }
  String day;
  if (thresholdDate.day() < 10) {
   day = '0' + thresholdDate.day();
  } else {
   day = thresholdDate.day().format();
  }
  String thresholdDateString = year + '-' + month + '-' + day + 'T23:59:59Z';

  query = 'SELECT Id, isActive, ProfileId, Email, UserName, CommunityNickname, FederationIdentifier, Federation_Id_2__c User WHERE Profile.Name = \'' + PROFILE_NAME + '\ AND isActive = true AND LastModifiedDate <= ' + thresholdDateString;

 }

 global Database.QueryLocator start(Database.BatchableContext BC) {
  System.debug(System.LoggingLevel.DEBUG, '##DEBUG: START - query: ' + query);
  return Database.getQueryLocator(query);
 }

 global void execute(Database.BatchableContext BC, List < User > users) {
  System.debug(System.LoggingLevel.DEBUG, '##DEBUG: execute begin. Number of users to process: ' + users.size());
  for (User inactiveProfileUser: users) {
   inactiveProfileUser.isActive = false;
   inactiveProfileUser.Username = INACTIVE_TEXT + inactiveProfileUser.UserName;
  }
  System.debug(System.LoggingLevel.DEBUG, '##DEBUG: Database Update List of Users: ' + users.size());
  List < Database.SaveResult > userSaveResults = Database.update(users, false);
  System.debug(System.LoggingLevel.DEBUG, 'Loop through list of saved results' + userSaveResults.size());
  // moved as global so that can access in finish
  //List < String > userDeactivationUpdateErrors = new List < String > ();
  for (Integer counter = 0; counter < userSaveResults.size(); counter++) {
   Database.SaveResult userSaveResult = userSaveResults[counter];
   if (!userSaveResult.isSuccess())
    System.debug(System.LoggingLevel.DEBUG, '##DEBUG: Errors exist for this userSave: ' + userSaveResult);
   for (Database.Error error: userSaveResult.getErrors()) {
    String errorMessageAndCode = 'User Deactivation Errors for User: ' + users[counter].Id + ': ';
    errorMessageAndCode += error.getStatusCode() + ':' + error.getMessage();
    userDeactivationUpdateErrors.add(errorMessageAndCode);

   }
  }


 }
 
 
 global void finish(Database.BatchableContext BC) {

 // building email body
   String messageHtmlBody = '<h2>User Deactivation Errors</h2> <br/>';
  if (!userDeactivationUpdateErrors.isEmpty()) {
   System.debug('##DEBUG: userDeactivationUpdateErrors exist: ' + userDeactivationUpdateErrors);
    for (String userDeactivationUpdateError: userDeactivationUpdateErrors) {
    messageHtmlBody += userDeactivationUpdateError + '<br/>'
   }

   // Sending email
   Messaging.SingleEmailmessage mail = new Messaging.SingleEmailMessage();
   mail.setToAddresses(new String[] {
    ERROR_EMAIL
   });
   mail.setSubject('User Deactivation Batch Errors:' + System.now() + ':Batch Job Id:' + BC.getJobId());
   mail.setHtmlBody('<p>The User Deactivation batch Apex job ' + BC.getJobId() + ' had the following errors:</p>' + messageHtmlBody);
   Messaging.sendEmail(new Messaging.MassEmailMessage[] { mail });


  }
 }
}
 
Amit Chaudhary 8Amit Chaudhary 8
Please try below code to execute
UserDeactivation_Batchable  obj = new UserDeactivation_Batchable();
            DataBase.executeBatch(obj);
NOTE:- you need to pass object of Batch job in executeBatch

DataBase.executeBatch(new UserDeactivation_Batchable() );

Please check below post for more information
1) http://amitsalesforce.blogspot.com/2016/02/batch-apex-in-salesforce-test-class-for.html

Let us know if this will help you
 
Rahavan Arumugam AlameluRahavan Arumugam Alamelu
Thanks all.... AS per the advise i have modifed the code and the same as below:

global class UserDeactivation_Batchable implements Database.Batchable < sObject > {
 global String query = '';
 List < String > userDeactivationUpdateErrors = new List < String > ();
 Batch_Job_Settings__c batchJobSettings = Batch_Job_Settings__c.getInstance('Batch Job Settings');
 Decimal DAYS_IN_THE_PAST = batchJobSettings.UD_Days_After_Last_Modified__c;
 String ERROR_EMAIL = batchJobSettings.UD_Error_Email__c;

  String PROFILE_NAME = batchJobSettings.UD_Profile_Name__c;
  String INACTIVE_TEXT = batchJobSettings.UD_Inactive_Text__c;
 
  String month;

 // constructor
 global UserDeactivation_Batchable() {

  // below line is wrong batchJobSettings.batchJobSettings
  Date thresholdDate = System.today().addDays(- DAYS_IN_THE_PAST.intValue());
  Integer year = thresholdDate.year();
  if (thresholdDate.month() < 10) {
   month = '0' + thresholdDate.month();
  } else {
   month = thresholdDate.month().format();
  }
  String day;
  if (thresholdDate.day() < 10) {
   day = '0' + thresholdDate.day();
  } else {
   day = thresholdDate.day().format();
  }
  String thresholdDateString = year + '-' + month + '-' + day + 'T23:59:59Z';

  query = 'SELECT Id, isActive, ProfileId, Email, UserName, CommunityNickname, FederationIdentifier, Federation_Id_2__c FROM User WHERE Profile.Name = \' '+ PROFILE_NAME + '\' AND isActive = true AND LastModifiedDate <= ' + thresholdDateString;

 }

 global Database.QueryLocator start(Database.BatchableContext BC) {
  System.debug(System.LoggingLevel.DEBUG, '##DEBUG: START - query: ' + query);
  return Database.getQueryLocator(query);
 }

 global void execute(Database.BatchableContext BC, List < User > users) {
  System.debug(System.LoggingLevel.DEBUG, '##DEBUG: execute begin. Number of users to process: ' + users.size());
  for (User inactiveProfileUser: users) {
   inactiveProfileUser.isActive = false;
      inactiveProfileUser.Username = INACTIVE_TEXT + inactiveProfileUser.UserName;
  }
  System.debug(System.LoggingLevel.DEBUG, '##DEBUG: Database Update List of Users: ' + users.size());
  List < Database.SaveResult > userSaveResults = Database.update(users, false);
  System.debug(System.LoggingLevel.DEBUG, 'Loop through list of saved results' + userSaveResults.size());
  // moved as global so that can access in finish
  //List < String > userDeactivationUpdateErrors = new List < String > ();
  for (Integer counter = 0; counter < userSaveResults.size(); counter++) {
   Database.SaveResult userSaveResult = userSaveResults[counter];
   if (!userSaveResult.isSuccess())
    System.debug(System.LoggingLevel.DEBUG, '##DEBUG: Errors exist for this userSave: ' + userSaveResult);
   for (Database.Error error: userSaveResult.getErrors()) {
    String errorMessageAndCode = 'User Deactivation Errors for User: ' + users[counter].Id + ': ';
    errorMessageAndCode += error.getStatusCode() + ':' + error.getMessage();
    userDeactivationUpdateErrors.add(errorMessageAndCode);

   }
  }


 }
 
 
 global void finish(Database.BatchableContext BC) {

 // building email body
   String messageHtmlBody = '<h2>User Deactivation Errors</h2> <br/>';
  if (!userDeactivationUpdateErrors.isEmpty()) {
   System.debug('##DEBUG: userDeactivationUpdateErrors exist: ' + userDeactivationUpdateErrors);
    for (String userDeactivationUpdateError: userDeactivationUpdateErrors) {
    messageHtmlBody += userDeactivationUpdateError + '<br/>';
   }

   // Sending email
   Messaging.SingleEmailmessage mail = new Messaging.SingleEmailMessage();
   mail.setToAddresses(new String[]{ERROR_EMAIL});
   mail.setSubject('User Deactivation Batch Errors:' + System.now() + ':Batch Job Id:' + BC.getJobId());
   mail.setHtmlBody('<p>The User Deactivation batch Apex job ' + BC.getJobId() + ' had the following errors:</p>' + messageHtmlBody);
   Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });


  }
 }
}



I have values for the fields of custom settings as below:

Batchsize = 2000
UD - Days After Last Modified = 7

Am getting below error when trying to execute the batch apex in ananymous window

System.NullPointerException: Attempt to de-reference a null object

Please advise.

Thanks
Rahavan
 
Rahavan Arumugam AlameluRahavan Arumugam Alamelu
Hi Pawan, I have modified the code now and am not getting compile time error now. But getting System.NullPointerException: Attempt to de-reference a null object error while executing the apex batch. Please advise. Thanks Rahavan
PawanKumarPawanKumar
Please execute below in anonymous 

try{
Database.executeBatch(new UserDeactivation_Batchable());
}catch(Exception e){
// please check in log on which line Nullpointer thrown
System.debug('Error:'+e);
}
Rahavan Arumugam AlameluRahavan Arumugam Alamelu
Thanks Pawan. The error is at Line number 5. I think the problem is at Decimal DAYS_IN_THE_PAST = batchJobSettings.UD_Days_After_Last_Modified__c; Regards, Rahavan
PawanKumarPawanKumar
Great to know. It worked for you.
Rahavan Arumugam AlameluRahavan Arumugam Alamelu
Pawan, Am not able to fix the error. Can you please advise. I have value for the UD_Days_After_Last_Modified__c in the custom settings Regards, rahavan
PawanKumarPawanKumar
1. what is the field type for "UD_Days_After_Last_Modified__c" in custom setting?
2. does this field have any value populated?
PawanKumarPawanKumar
Please execute below and see what it print for Bold Highlighted in log.
try{
Batch_Job_Settings__c batchJobSettings = Batch_Job_Settings__c.getInstance('Batch Job Settings');
  // below should not print null 
  System.debug('Queried batchJobSettings:'+batchJobSettings);

Database.executeBatch(new UserDeactivation_Batchable());
}catch(Exception e){
// please check in log on which line Nullpointer thrown
System.debug('Error:'+e);
}
Rahavan Arumugam AlameluRahavan Arumugam Alamelu
The field type is ‘Number’ with the length of ‘18’. This field has default value 7 Thanks Rahavan
Rahavan Arumugam AlameluRahavan Arumugam Alamelu
Am getting null value for 'Queried batchJobSettings: I like to get used to salesforce. Need your assistance. Regards, Rahavan
PawanKumarPawanKumar
Batch_Job_Settings__c batchJobSettings = Batch_Job_Settings__c.getInstance('Batch Job Settings');
  Please replace below above line with below statement.
  
// Please add other field in select
  Batch_Job_Settings__c batchJobSettings = [SELECT id,UD_Days_After_Last_Modified__c, "Other Required Field" FROM Batch_Job_Settings__c limit 1];
Rahavan Arumugam AlameluRahavan Arumugam Alamelu
Tried as per your input but still the same error Also I have attempted by recreating the custom setting value fields. Regards, Rahavan
Rahavan Arumugam AlameluRahavan Arumugam Alamelu
Pawan, Am able to execute the batch apex. But the code didn’t worked as expected. It is not deactivating the user profile which got last modified 7 days before. I have one chatter free user whose profile got last modified in July, but this user is still active. Kindly advise Thanks Rahavan
PawanKumarPawanKumar
Please take the query logged in your debug log and check whether that record has been picked up by your batch or not?
System.debug(System.LoggingLevel.DEBUG, '##DEBUG: START - query: ' + query);

 
PawanKumarPawanKumar
have u got the root cause?
Rahavan Arumugam AlameluRahavan Arumugam Alamelu
Pawan, Good day to you. The job got executed successfully and deactivated the user. What am trying to do now is to make the job activate Chatter free user whose profile is not active and got last modified after past 7 days. I have made the related changes in the code. But the script is not activating the profile. Am not getting any error while execution and presume that the DML is not happening on the record. Please advise global class UserDeactivation_Batchable implements Database.Batchable { global String query = ''; List < String > userDeactivationUpdateErrors = new List < String > (); //Batch_Job_Settings__c bat = [SELECT UD_Days_After_Last_Modified__c,UD_Error_Email__c,UD_Profile_Name__c,UD_Inactive_Text__c FROM Batch_Job_Settings__c limit 1]; BatchJobSettings__c UDBatchJobSettings = BatchJobSettings__c.getInstance('UDBatchJobSettings'); //Batch_Job_Settings__c batchJobSettings = Batch_Job_Settings__c.getInstance('Batch_Job_Settings'); //BatchJobSettings__c BatchJobSettings=BatchJobSettingsInstance('BatchJobSettings'); Decimal DAYS_IN_THE_PAST = UDBatchJobSettings.UD_Days_After_Last_Modified__c; String ERROR_EMAIL = UDBatchJobSettings.UD_Error_Email__c; String PROFILE_NAME = UDBatchJobSettings.UD_ProfileName__c; String INACTIVE_TEXT = UDBatchJobSettings.UD_Inactive_Text__c; String month; // constructor global UserDeactivation_Batchable() { // below line is wrong batchJobSettings.batchJobSettings Date thresholdDate = System.today().addDays(- DAYS_IN_THE_PAST.intValue()); Integer year = thresholdDate.year(); if (thresholdDate.month() < 10) { month = '0' + thresholdDate.month(); } else { month = thresholdDate.month().format(); } String day; if (thresholdDate.day() < 10) { day = '0' + thresholdDate.day(); } else { day = thresholdDate.day().format(); } String thresholdDateString = year + '-' + month + '-' + day + 'T23:59:59Z'; //made changes here query = 'SELECT Id, isActive, ProfileId, Email, UserName FROM User WHERE Profile.Name = \'' + PROFILE_NAME + '\' AND isActive = false AND LastModifiedDate >= ' + thresholdDateString; } global Database.QueryLocator start(Database.BatchableContext BC) { System.debug(System.LoggingLevel.DEBUG, '##DEBUG: START - query: ' + query); return Database.getQueryLocator(query); } global void execute(Database.BatchableContext BC, List < User > users) { System.debug(System.LoggingLevel.DEBUG, '##DEBUG: execute begin. Number of users to process: ' + users.size()); for (User inactiveProfileUser: users) { //made change here inactiveProfileUser.isActive = True; inactiveProfileUser.Username = INACTIVE_TEXT + inactiveProfileUser.UserName; } System.debug(System.LoggingLevel.DEBUG, '##DEBUG: Database Update List of Users: ' + users.size()); List < Database.SaveResult > userSaveResults = Database.update(users, false); System.debug(System.LoggingLevel.DEBUG, 'Loop through list of saved results' + userSaveResults.size()); // moved as global so that can access in finish //List < String > userDeactivationUpdateErrors = new List < String > (); for (Integer counter = 0; counter < userSaveResults.size(); counter++) { Database.SaveResult userSaveResult = userSaveResults[counter]; if (!userSaveResult.isSuccess()) System.debug(System.LoggingLevel.DEBUG, '##DEBUG: Errors exist for this userSave: ' + userSaveResult); for (Database.Error error: userSaveResult.getErrors()) { String errorMessageAndCode = 'User Deactivation Errors for User: ' + users[counter].Id + ': '; errorMessageAndCode += error.getStatusCode() + ':' + error.getMessage(); userDeactivationUpdateErrors.add(errorMessageAndCode); } } } global void finish(Database.BatchableContext BC) { // building email body String messageHtmlBody = '

User Deactivation Errors


'; if (!userDeactivationUpdateErrors.isEmpty()) { System.debug('##DEBUG: userDeactivationUpdateErrors exist: ' + userDeactivationUpdateErrors); for (String userDeactivationUpdateError: userDeactivationUpdateErrors) { messageHtmlBody += userDeactivationUpdateError + '
'; } // Sending email Messaging.SingleEmailmessage mail = new Messaging.SingleEmailMessage(); mail.setToAddresses(new String[]{ERROR_EMAIL}); mail.setSubject('User Deactivation Batch Errors:' + System.now() + ':Batch Job Id:' + BC.getJobId()); mail.setHtmlBody('

The User Deactivation batch Apex job ' + BC.getJobId() + ' had the following errors:

' + messageHtmlBody); Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail }); } } } Thanks Rahavan