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
grangran 

Whats the best way to pass a value from a VF Page Controller to an Apex Batch Class?

Hi

I wanna pass the value of a Campaign ID from a VF Page controller to an Apex Batch Class.

Here is my VF Controller's function:

public with sharing class SendCECertificate {
     public Campaign CAMP { get; set; }
     public Campaign CAMPID { get; set; }
    
     // Class Constructor
      public SendCECertificate(ApexPages.StandardController controller){
         CAMP =  (Campaign)controller.getRecord();              CAID = (Id)CAMP.Id; 
         CAMPID = (Id)CAMP.Id;     // this works fine
      }

      // This function is called from a commandLink  on a VF page
      public void sendEmail(){      
        // Invoke Batchclass from here....
        Database.executeBatch(new SendEmailBatchable(null), 10);
        // Keeping size to 10 to be under emailing governor limits... but how do we pass the CAMPID here? Can this function be overloaded?
    }


And then in the Apex Batch class, I wanna fetch the CAMPID

Here is the batchable class....

global class SendEmailBatchable implements Database.Batchable<SObject>, Database.Stateful {
private String query;
    private Id jobId;   
   
    global SendEmailBatchable(String query) {       
        this.query = query;
        if (this.query == null) {           
          this.query = 'SELECT Attended_CE_Training__c, CE_Credit_Certificate_Sent__c, CE_Credit_Certificate_Sent_Date__c, CampaignId, Id,ContactId, Event_Campaign_Comments__c, Primary_Language__c, RecordTypeId, RecordType.Name, Status, Contact.FirstName, Contact.Email FROM CampaignMember where CampaignId=\'701c0000000CHHz\' ' ;    // NOTE: I wanna replace this hardcoded ID with CAMPID which has to be sent from the VF controller
        }
    }
   
     global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator(query);
    }
   
    global void execute(Database.BatchableContext bc, List<SObject> batch) {    
      sendMail((List<CampaignMember>) batch );
      // Logic to fire email in batches of 10 as follows.....
     
    }
   
     public static void sendMail(List<CampaignMember> batch){
     
     }
    
     global void finish(Database.BatchableContext bc) {
         // Send a a confirmation email to the User who invoked the email blast
         ////// Database.executeBatch(new EAppBatchable(null), 2000);
    }
   
}

Any suggestions, what is the best way to do this?

Thanks
VK
Best Answer chosen by gran
Pavan Kumar KajaPavan Kumar Kaja
Finally try this below code and let me know its working or not.

public with sharing class SendCECertificate {
     public Campaign CAMP { get; set; }
     public Campaign CAMPID { get; set; }
    
     // Class Constructor
      public SendCECertificate(ApexPages.StandardController controller){
         CAMP =  (Campaign)controller.getRecord();              CAID = (Id)CAMP.Id; 
         CAMPID = (Id)CAMP.Id;     // this works fine
      }

      // This function is called from a commandLink  on a VF page
      public void sendEmail(){      
		if(CAMPID != null){
			SendEmailBatchable batch = new SendEmailBatchable(CAMPID);
			Database.executeBatchatch(batch,10);
		}
    }
}
global class SendEmailBatchable implements Database.Batchable<SObject>, Database.Stateful {
private String query ='';
    private Id jobId;   
   
    global SendEmailBatchable(String CAMPID) {       
        query = 'SELECT Attended_CE_Training__c, CE_Credit_Certificate_Sent__c, CE_Credit_Certificate_Sent_Date__c, CampaignId, Id,ContactId, Event_Campaign_Comments__c, Primary_Language__c, RecordTypeId, RecordType.Name, Status, Contact.FirstName, Contact.Email FROM CampaignMember where CampaignId=:CAMPID' ;    // NOTE: I wanna replace this hardcoded ID with CAMPID which has to be sent from the VF controller
    }
   
     global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator(query);
    }
   
    global void execute(Database.BatchableContext bc, List<SObject> batch) {    
      sendMail((List<CampaignMember>) batch );
      // Logic to fire email in batches of 10 as follows.....
     
    }
   
     public static void sendMail(List<CampaignMember> batch){
     
     }
    
     global void finish(Database.BatchableContext bc) {
         // Send a a confirmation email to the User who invoked the email blast
         ////// Database.executeBatch(new EAppBatchable(null), 2000);
    }
   
}



All Answers

Ramu_SFDCRamu_SFDC
See if the below article helps

http://bobbuzzard.blogspot.com/2011/07/passing-parameters-to-apex-method-from.html
grangran
Thanks Ramu. It talks about passing values to controllers, however, I'm still not sure how to pass a value to a Batchable class. 

Any other suggestions?
Pavan Kumar KajaPavan Kumar Kaja

SendEmailBatchable  batchObj = new SendEmailBatchable();
batchObj.query='SELECT Attended_CE_Training__c, CE_Credit_Certificate_Sent__c, CE_Credit_Certificate_Sent_Date__c, CampaignId, Id,ContactId, Event_Campaign_Comments__c, Primary_Language__c, RecordTypeId, RecordType.Name, Status, Contact.FirstName, Contact.Email FROM CampaignMember where CampaignId=:CAMPID';
Database.BatchableContext bc;
batchObj.start(bc);
batchObj.execute(bc,Aps);
batchObj.finish(bc);


I have used above code in test class its worked for me. and I havent tested above code in controller, but you can still try this. it may work.
grangran
Thanks for your reply. In your sample code, you have created an instance of the batchable class, assigned a query to it and run it using the start,, execute & finish methods.

However, the CAMPID still remains null. What I am trying to achieve is to set the value of CAMPID, which is a variable inside the batchable class, and assign it a value from an external controller.

So basically I have two Apex classes, 1st is a VF Page Controller, 2nd is an Apex Batchable class, which when invoked goes into queue and executes when resources on the cloud are free.

So I'm still trying to figure out a way how to pass a value to the variable CAMPID in the batchable class. I do have a value for CAMPID in the VF Controller & wanna assign it to the batchable class. From the VF page controller, I'll simply invoke the Database.executeBatch(new sendEmailBatchable(null), 10); method but I'm not sure how to pass the value of CAMPID to this method. Is there a way I can overload this method?
Pavan Kumar KajaPavan Kumar Kaja
Finally try this below code and let me know its working or not.

public with sharing class SendCECertificate {
     public Campaign CAMP { get; set; }
     public Campaign CAMPID { get; set; }
    
     // Class Constructor
      public SendCECertificate(ApexPages.StandardController controller){
         CAMP =  (Campaign)controller.getRecord();              CAID = (Id)CAMP.Id; 
         CAMPID = (Id)CAMP.Id;     // this works fine
      }

      // This function is called from a commandLink  on a VF page
      public void sendEmail(){      
		if(CAMPID != null){
			SendEmailBatchable batch = new SendEmailBatchable(CAMPID);
			Database.executeBatchatch(batch,10);
		}
    }
}
global class SendEmailBatchable implements Database.Batchable<SObject>, Database.Stateful {
private String query ='';
    private Id jobId;   
   
    global SendEmailBatchable(String CAMPID) {       
        query = 'SELECT Attended_CE_Training__c, CE_Credit_Certificate_Sent__c, CE_Credit_Certificate_Sent_Date__c, CampaignId, Id,ContactId, Event_Campaign_Comments__c, Primary_Language__c, RecordTypeId, RecordType.Name, Status, Contact.FirstName, Contact.Email FROM CampaignMember where CampaignId=:CAMPID' ;    // NOTE: I wanna replace this hardcoded ID with CAMPID which has to be sent from the VF controller
    }
   
     global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator(query);
    }
   
    global void execute(Database.BatchableContext bc, List<SObject> batch) {    
      sendMail((List<CampaignMember>) batch );
      // Logic to fire email in batches of 10 as follows.....
     
    }
   
     public static void sendMail(List<CampaignMember> batch){
     
     }
    
     global void finish(Database.BatchableContext bc) {
         // Send a a confirmation email to the User who invoked the email blast
         ////// Database.executeBatch(new EAppBatchable(null), 2000);
    }
   
}



This was selected as the best answer
grangran
It worked Ashi, thanks, though I made a minor tweak in it. Because the sendEmailBatchable constructor was handling the SOQL query, I let it be as is, and instead I overloaded this constructor by adding one more paramater to this constructor. Like this:

global SendEmailBatchable(String query, String qstr) {       
        this.query = query;
        if (this.query == null) {           
         
          this.query = 'SELECT Attended_CE_Training__c, CE_Credit_Certificate_Sent__c, CE_Credit_Certificate_Sent_Date__c, CampaignId, Id,ContactId, Event_Campaign_Comments__c, Primary_Language__c, RecordTypeId, RecordType.Name, Status, Contact.FirstName, Contact.Email FROM CampaignMember where CampaignId=:qstr' ;    // HERE the value of qstr is passed from the VF page's controller
        }
    }

and in the VF page controller, I added the following:

public void sendCECertificate() {
      String qstr =''; // qstr is nothing but the Campaign Id
        qstr = ApexPages.currentPage().getParameters().get('CAMPID');
        if(qstr!=null){
             Database.executeBatch(new SendCECertificatesBatchable(null,qstr), 10);
        }
}

and it works good... thanks bud!