You need to sign in to do that
Don't have an account?
Radhe Shyam
How to schedule apex class after every 5 minutes
Here is my apex batch:
global class EmailAlertToQuoteProposalApprovalUser implements Database.Batchable<sObject>, database.stateful{
public String EVENT_TYPE_MEETING = 'Meeting';
private Datetime EndTime=System.now();
private String query;
public String limitSize;
private long recordcount;
private string debuglog='';
private integer batchcounter=0;
private datetime processstarttime=system.now();
private boolean haserror=false;
private set<id> processedaccounts=new set<id>();
global EmailAlertToQuoteProposalApprovalUser(datetime activitydatetime){
if(activitydatetime==null){
EndTime=System.now().adddays(-1);
}
}
global Database.QueryLocator start(Database.BatchableContext BC){
log('Batch process start time: ' + processstarttime);
log('Batch process id: ' + bc.getJobID());
log('Acvitity End Time Parameter: ' + EndTime);
Datetime dtTimeNow=system.now();
query='SELECT Id,Pending_With_Email__c,Submitted_Date_time__c FROM Apttus_Proposal__Proposal__c WHERE Submitted_Date_time__c!=null AND Submitted_Date_time__c>=: dtTimeNow' + ' ORDER BY Id';
if(limitSize!=null)
{
query = query + ' LIMIT ' + limitSize;
}
log(query);
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<sObject> scope){
log('Batch number: ' + batchcounter);
set<id> QuoteProposalId=new set<id>();
list<Apttus_Proposal__Proposal__c> lstQuoteProposal=new list<Apttus_Proposal__Proposal__c>();
for(sobject so: scope){
id quoteid=(Id)so.get('Id');
Apttus_Proposal__Proposal__c objQuote= (Apttus_Proposal__Proposal__c)so;
if(!processedaccounts.contains(quoteid)){
QuoteProposalId.add(quoteid);
lstQuoteProposal.add(objQuote);
}
}
if(QuoteProposalId.size()>0){
log('Number of accounts to be processed: ' + QuoteProposalId.size());
log('Account Ids: '+ QuoteProposalId);
List<String> CCAddress=new List<String>();
CCAddress.add('abaranwal@kloudrac.com');
string TemplateId=system.Label.quoteEmailTemplate;
processedaccounts.addAll(QuoteProposalId);
try{
Messaging.SingleEmailMessage[] mails=new Messaging.SingleEmailMessage[0];
for(Apttus_Proposal__Proposal__c qt:lstQuoteProposal){
list<string> AdditionalRecipients=new list<string>();
AdditionalRecipients.add(qt.Pending_With_Email__c);
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(AdditionalRecipients);
mail.setCcAddresses(CCAddress);
//mail.setOrgWideEmailAddressId(OrgWideEmailId);
mail.setTemplateId(TemplateId);
mail.whatid=qt.id;
mail.setTargetObjectId('003n0000008FULE');
mails.add(mail);
}
log('Sending emails ... count: ' + mails);
Messaging.sendEmail(mails);
}catch(Exception e) {
haserror=true;
string body=e.getMessage();
log(body);
}
}else{
log('No Quote/Proposal is processed in this batch');
}
++batchcounter;
}
global void finish(Database.BatchableContext BC){
log('Entire batch process has ended');
SaveDebugLog();
}
public static void SendEmail(String Subject,String Body,String[] Recipeints){
/*String Displayname=Lookup.getTarget('UpdateOpportunity', 'Config','FromAddress', true);
//OneCRM.sandbox@ge.com
Id OrgWideEmailId=[Select Id, DisplayName, Address from OrgWideEmailAddress where Address =:Displayname].Id;
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(Recipeints);
mail.setSubject(Subject);
mail.setPlainTextBody(Body);
mail.setOrgWideEmailAddressId(OrgWideEmailId);
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});*/
}
private void log(string msg){
debuglog+=msg+'\n';
system.debug(logginglevel.info,msg);
}
private Id SaveDebugLog(){
String recStr = 'Transaction Log';
Integration_Log__c log= new Integration_Log__c();
log.Call_Method__c = 'BatchProcessQuoteProposalEscalationEmail';
log.Object_Name__c = 'Quote/Proposal';
log.Call_Time__c = processstarttime;
log.Status__c = haserror?'Failure':'Success';
insert log;
recStr += '\nInterfaceId:' + log.Object_Name__c;
recStr += '\nObjectId:' + log.Object_Id__c;
recStr += '\nCallTime:' + log.Call_Time__c.format('yyyy.MM.dd HH:mm:ss.SSS z');
recStr += '\nStatus:' + log.Status__c;
recStr += '\nLogId:'+ log.Id;
recStr += '\n';
recStr += debuglog;
Blob recBlob= Blob.valueOf(recStr);
Attachment att= new attachment();
att.Name = 'Log Details ' +system.now()+'.txt';
att.ParentId = log.Id;
att.Body = Blob.valueof(recStr);
insert att;
return log.id;
}
public static void startbatch(datetime activitytime){
EmailAlertToQuoteProposalApprovalUser aula=new EmailAlertToQuoteProposalApprovalUser(activitytime);
aula.log('activitytime: ' + activitytime);
aula.EndTime=activitytime;
if(activitytime==null){
aula.EndTime=System.now().adddays(-1);
}
ID batchprocessid = Database.executeBatch(aula);
System.debug('Apex Job id: ' + batchprocessid );
}
}
And here is schedulable: I want to run batch file after every 5 minutes... Please Help
===============================================
global class scheduledQuoteReminderBatchable implements Schedulable {
global void execute(SchedulableContext sc) {
EmailAlertToQuoteProposalApprovalUser aula=new EmailAlertToQuoteProposalApprovalUser(system.now());
ID batchprocessid = Database.executeBatch(aula);
}
}
global class EmailAlertToQuoteProposalApprovalUser implements Database.Batchable<sObject>, database.stateful{
public String EVENT_TYPE_MEETING = 'Meeting';
private Datetime EndTime=System.now();
private String query;
public String limitSize;
private long recordcount;
private string debuglog='';
private integer batchcounter=0;
private datetime processstarttime=system.now();
private boolean haserror=false;
private set<id> processedaccounts=new set<id>();
global EmailAlertToQuoteProposalApprovalUser(datetime activitydatetime){
if(activitydatetime==null){
EndTime=System.now().adddays(-1);
}
}
global Database.QueryLocator start(Database.BatchableContext BC){
log('Batch process start time: ' + processstarttime);
log('Batch process id: ' + bc.getJobID());
log('Acvitity End Time Parameter: ' + EndTime);
Datetime dtTimeNow=system.now();
query='SELECT Id,Pending_With_Email__c,Submitted_Date_time__c FROM Apttus_Proposal__Proposal__c WHERE Submitted_Date_time__c!=null AND Submitted_Date_time__c>=: dtTimeNow' + ' ORDER BY Id';
if(limitSize!=null)
{
query = query + ' LIMIT ' + limitSize;
}
log(query);
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<sObject> scope){
log('Batch number: ' + batchcounter);
set<id> QuoteProposalId=new set<id>();
list<Apttus_Proposal__Proposal__c> lstQuoteProposal=new list<Apttus_Proposal__Proposal__c>();
for(sobject so: scope){
id quoteid=(Id)so.get('Id');
Apttus_Proposal__Proposal__c objQuote= (Apttus_Proposal__Proposal__c)so;
if(!processedaccounts.contains(quoteid)){
QuoteProposalId.add(quoteid);
lstQuoteProposal.add(objQuote);
}
}
if(QuoteProposalId.size()>0){
log('Number of accounts to be processed: ' + QuoteProposalId.size());
log('Account Ids: '+ QuoteProposalId);
List<String> CCAddress=new List<String>();
CCAddress.add('abaranwal@kloudrac.com');
string TemplateId=system.Label.quoteEmailTemplate;
processedaccounts.addAll(QuoteProposalId);
try{
Messaging.SingleEmailMessage[] mails=new Messaging.SingleEmailMessage[0];
for(Apttus_Proposal__Proposal__c qt:lstQuoteProposal){
list<string> AdditionalRecipients=new list<string>();
AdditionalRecipients.add(qt.Pending_With_Email__c);
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(AdditionalRecipients);
mail.setCcAddresses(CCAddress);
//mail.setOrgWideEmailAddressId(OrgWideEmailId);
mail.setTemplateId(TemplateId);
mail.whatid=qt.id;
mail.setTargetObjectId('003n0000008FULE');
mails.add(mail);
}
log('Sending emails ... count: ' + mails);
Messaging.sendEmail(mails);
}catch(Exception e) {
haserror=true;
string body=e.getMessage();
log(body);
}
}else{
log('No Quote/Proposal is processed in this batch');
}
++batchcounter;
}
global void finish(Database.BatchableContext BC){
log('Entire batch process has ended');
SaveDebugLog();
}
public static void SendEmail(String Subject,String Body,String[] Recipeints){
/*String Displayname=Lookup.getTarget('UpdateOpportunity', 'Config','FromAddress', true);
//OneCRM.sandbox@ge.com
Id OrgWideEmailId=[Select Id, DisplayName, Address from OrgWideEmailAddress where Address =:Displayname].Id;
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(Recipeints);
mail.setSubject(Subject);
mail.setPlainTextBody(Body);
mail.setOrgWideEmailAddressId(OrgWideEmailId);
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});*/
}
private void log(string msg){
debuglog+=msg+'\n';
system.debug(logginglevel.info,msg);
}
private Id SaveDebugLog(){
String recStr = 'Transaction Log';
Integration_Log__c log= new Integration_Log__c();
log.Call_Method__c = 'BatchProcessQuoteProposalEscalationEmail';
log.Object_Name__c = 'Quote/Proposal';
log.Call_Time__c = processstarttime;
log.Status__c = haserror?'Failure':'Success';
insert log;
recStr += '\nInterfaceId:' + log.Object_Name__c;
recStr += '\nObjectId:' + log.Object_Id__c;
recStr += '\nCallTime:' + log.Call_Time__c.format('yyyy.MM.dd HH:mm:ss.SSS z');
recStr += '\nStatus:' + log.Status__c;
recStr += '\nLogId:'+ log.Id;
recStr += '\n';
recStr += debuglog;
Blob recBlob= Blob.valueOf(recStr);
Attachment att= new attachment();
att.Name = 'Log Details ' +system.now()+'.txt';
att.ParentId = log.Id;
att.Body = Blob.valueof(recStr);
insert att;
return log.id;
}
public static void startbatch(datetime activitytime){
EmailAlertToQuoteProposalApprovalUser aula=new EmailAlertToQuoteProposalApprovalUser(activitytime);
aula.log('activitytime: ' + activitytime);
aula.EndTime=activitytime;
if(activitytime==null){
aula.EndTime=System.now().adddays(-1);
}
ID batchprocessid = Database.executeBatch(aula);
System.debug('Apex Job id: ' + batchprocessid );
}
}
And here is schedulable: I want to run batch file after every 5 minutes... Please Help
===============================================
global class scheduledQuoteReminderBatchable implements Schedulable {
global void execute(SchedulableContext sc) {
EmailAlertToQuoteProposalApprovalUser aula=new EmailAlertToQuoteProposalApprovalUser(system.now());
ID batchprocessid = Database.executeBatch(aula);
}
}
http://resources.docs.salesforce.com/198/10/en-us/sfdc/pdf/salesforce_app_limits_cheatsheet.pdf
Beware though, as batch classes hardly ever kick off on time. That is, they kick off whenever the resources are available after they are supposed to start. I've gone down the "run batch apex every 5 minute" road before, and the batch jobs typically overlap pretty quickly. In other words, I would consider spacing your batch jobs out to at least 15 minutes.
I am new in this apex batch and all,
please help me out to write the proper code: How to insert your code in this below code.....or we need to write some othe class file?
global class scheduledQuoteReminderBatchable implements Schedulable {
global void execute(SchedulableContext sc) {
EmailAlertToQuoteProposalApprovalUser aula=new EmailAlertToQuoteProposalApprovalUser(system.now());
ID batchprocessid = Database.executeBatch(aula);
}
}
You don't need to insert my code into your code. If you have valid scheduable class then you need to run each block of below code in developer console. That will schedule your batch class.
Check this out: http://howtodoitinsalesforce.blogspot.in/2016/12/run-schedule-class-in-every-5-mins-in.html
Try to use Schedule Helper. Allows you to manage your schedules to execute even every 5 minutes.
From AppExchange - https://appexchange.salesforce.com/listingDetail?listingId=a0N3A00000DqCmYUAV
I was looking for something a bit more clever than the self rescheduling trick. The problem with that is when salesforce gets busy, that can turn a once in every 1 minute schedule to a once every 5 minute schedule... So far no simple solutions, just complex ones.
This wouldn't be such an issue if salesforce would implement the ability to schedule more than once an hour, or if they were to make managed packages use their own schedule queue, rather than sharing same queue with unmanaged applications.
You can use this logic to achieve it:
Integer frequency = 15; // interval in minutes you want apex to schedule ie. 2, 3, 5, 10, 15
Integer totalIterations = 60/frequency - 1;
for(Integer i = 0; i <= totalIterations; i++){
Integer count = i*frequency;
String minuteString = (count < 10) ? '0' + count : '' + count;
System.schedule('Scheduled Job ' + i, '0 ' + minuteString + ' * * * ?', new ApexScheduler()); // ApexScheduler is a class that implements schedulable interface
}
Let me know if you have any questions.
Best,
Jatin Narula
// The scheduler class :-
global without sharing class SchedulerClass2 implements Schedulable
{
Integer count = 0;
Integer gapMinutes = 5;
public void execute(SchedulableContext sc) {
System.debug(LoggingLevel.INFO, '#### execute method starts of SchedulerClass2');
// Re-schedule only once if "Check x min trigger" field does not have
// value "WorkerClass" in it. This is a custom field of type text on Account object.
// API name of this field is :-
Account a = [Select id, name, Check_x_min_trigger__c from Account where name = 'ListAcc10000'];
// Create an account with name = 'ListAcc10000'. Keep its field "Check x min trigger" empty.
System.debug(LoggingLevel.INFO, '#### queried account is ' + a);
System.debug(LoggingLevel.INFO, '#### queried account Check_x_min_trigger__c is ' + a.Check_x_min_trigger__c);
// When the batch class code runs, it will populate the value "WorkerClass" in the field "Check x min trigger"
// of all the accounts in the database
if(a.Check_x_min_trigger__c != 'WorkerClass')
{
System.debug(LoggingLevel.INFO, '#### rescheduling SchedulerClass2');
// Re-schedule ourself 5 times to run again at gap of 5 minutes
while(count < 5) {
DateTime now = DateTime.now();
DateTime nextRunTime = now.addMinutes(gapMinutes);
System.debug(LoggingLevel.INFO, '#### nextRunTime is ' + nextRunTime);
String cronString = '' + nextRunTime.second() + ' ' + nextRunTime.minute() + ' ' +
nextRunTime.hour() + ' ' + nextRunTime.day() + ' ' +
nextRunTime.month() + ' ? ' + nextRunTime.year();
// format for cronString is seconds minutes hours day_of_month month day_of_week year
System.debug(LoggingLevel.INFO, '#### calculated cronString is ' + cronString);
System.schedule(SchedulerClass2.class.getName() + '-' + nextRunTime.format(), cronString, new SchedulerClass2());
count++;
System.debug(LoggingLevel.INFO, '#### count incremented, new count is ' + count);
gapMinutes = gapMinutes + 5; // add gap of 5 minutes for each future run.
System.debug(LoggingLevel.INFO, '#### gapMinutes incremented, new gapMinutes is ' + gapMinutes);
}
}
// Launch a batch job to do the actual work
WorkerClass wc = new WorkerClass();
System.debug(LoggingLevel.INFO, '#### about to call executeBatch of WorkerClass');
Database.executeBatch(wc);
}
}
// The batch class which will do the actual work. It will populate the value "WorkerClass" in the custom field
// "Check x min trigger" on all account records in the database.
global class WorkerClass implements Database.Batchable<SObject>
{
global Database.QueryLocator start(Database.BatchableContext bc)
{
String query = 'Select id, name, City__c, Check_x_min_trigger__c from Account';
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, list<SObject> scope)
{
System.debug(LoggingLevel.INFO, '#### execute method of batch class starts in WorkerClass');
List<Account> accLstToUpdate = new List<Account>();
if(scope != null)
{
List<Account> accLst = (List<Account>)scope;
for(Account a : accLst)
{
a.Check_x_min_trigger__c = 'WorkerClass';
accLstToUpdate.add(a);
}
if(accLstToUpdate.size() > 0)
{
System.debug(LoggingLevel.INFO, '#### execute method of batch class: updating accLstToUpdate ' + accLstToUpdate.size());
update accLstToUpdate;
}
}
}
global void finish(Database.BatchableContext BC)
{
System.debug(LoggingLevel.INFO, '#### finish method of batch class');
}
}
From Developer Console -> Execute Anonymous, call the scheduler class :-
SchedulerClass2 sc2 = new SchedulerClass2();
String stringTime = '0 55 * * * ?'; // will run at 55 minutes past every hour
String jobID = system.schedule('SchedulerClass2Scheduler', stringTime, sc2);
Go to Setup -> Jobs -> Scheduled Jobs to see the future run Apex Scheduler jobs queued up.
There's a video walkthrough here and there's links to my github code example in the video's description: https://youtu.be/NjY51eURQXc
private final String JOBNAME = 'Repeating Job';
private final Integer FIVEMINUTE =5;
public void execute(SchedulableContext cont)
{ System.debug('every 5 min');
findAndAbortJob(cont);
}
private void findAndAbortJob(SchedulableContext cont)
{
if (cont == null)
{
return;
}
List<CronJobDetail> cronDetail = [SELECT Id FROM CronJobDetail WHERE Name= :JOBNAME LIMIT 1];
if (cronDetail.isEmpty())
{
return;
}
List<CronTrigger> cronTriggers = [SELECT Id FROM CronTrigger WHERE CronJobDetailId = :cronDetail[0].Id];
if(cronTriggers.isEmpty())
{
return;
}
try
{
System.abortJob(cronTriggers[0].Id);
rescheduleJob();
}
catch (Exception e)
{
System.debug('This was the error ::: ' + e.getMessage());
}
}
public void rescheduleJob()
{
Datetime sysTime = System.now().addMinutes(FIVEMINUTE);
String cronExpression = '' + sysTime.second() + ' ' + sysTime.minute() + ' ' + sysTime.hour() + ' ' + sysTime.day() + ' ' + sysTime.month() + ' ? ' + sysTime.year();
System.schedule(JOBNAME, cronExpression, new testScheduleClass());
}
}
Hi Radhe,
Cron Expression to run a Job every 5 Minutes is given below
If you find your Solution then mark this as the best answer.
Thank you!
Regards,
Suraj Tripathi
Here is the way I do this. First I install https://github.com/docbill/Managed-Scheduled-Apex/projects (https://github.com/docbill/Managed-Scheduled-Apex/projects) into my org, and use the quickstart command to schedule with the maximum frequency I need for my batch jobs. At Red Hat we use once every two minutes, because experience has taught us a higher frequency just creates too much locking.
Then I implement my class extending AbstractBatchableBase or AbstractBatchable. The main difference here between just using the Batchable interface, is I can implement a hasWork() method to return false, where there are no records to process, avoiding the batch call. I usually will not hard code constants inside my batch job, but instead allow the constants to be assigned by a json constructor.
Here is a screen shot of scheduled jobs and what type of values we configure:
Notice how we actually can run Cleanup_Batchable under many different input sets for cleaning up different types of records. So it means less code overall. Adding a new cleanup job is typically a 2 point story. The effort is mainly testing to make sure we configured the job correctly.
While the other answers people are giving you are correct, they are only good for a small org with very few scheduled jobs running. You'll quickly find all your available jobs slots are full if you try to schedule many jobs multiple times per hour. Almost all our jobs slots at Red Hat are filled by managed packages, which don't give us the ability to use our managed scheduled apex class.
However, this is also very dark path. As ultimately scheduled jobs eventually are limited in how much they can be scaled. And if you get too many of them, you'll find you start to become bottlenecked.
BTW. I decided to add the Cleanup_Batchable class to the open source. As this job contains no internal business logic for Red Hat, and is a good example that many would actually use without need to modify it.
And here is an example json constructor from the screen shot in my previous post:
This particular job we don't run more than once an hour. If someone wanted to run this more frequently, they would probably want to add constants for MINUTES.
There is a simpler approach to scheduling a Job every 5 minutes -- simply create a schedulable job, and then a reschedule routine -- such as that shown below:
global class Case_Escalations_Process_Job implements Schedulable {
global void execute(SchedulableContext context) {
// Apex code for the job
// As a last step run the RescheduleJob() subroutine shown below:
RescheduleJob();
}
}
public void RescheduleJob(){
// If job currently scheduled remove it
List<CronTrigger> SchJobs = [SELECT Id FROM CronTrigger where CronJobDetail.Name = 'Case Escalations Process Job'];
String MyJobID;
if (SchJobs.size() > 0){
MyJobID = SchJobs[0].Id;
// removing the job from the schedule
System.abortjob(MyJobID);
}
// calculating the minute mark which is 5 minutes from now
DateTime Cdatetime = DateTime.now();
DateTime NewDateTime;
NewDateTime = Cdatetime.addMinutes(5); // Reschedule job in 5 minutes from time job finishes
Integer min = NewDateTime.minute();
// scheduling job for a certain minute of the hour
String sch = '0 ' + string.valueOf(min) + ' * * * ? ';
// rescheduling the job
System.schedule('Case Escalations Process Job', sch, new Case_Escalations_Process_Job());
}