• Prak088
  • NEWBIE
  • 0 Points
  • Member since 2013

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 0
    Questions
  • 5
    Replies

Hi,

 

I have a problem trying to create my first apex batch.

 

I have got a trigger, that checks if an account has been modified. If so, I add the id of the account to a list and at pass the list of ids to the apex batch.

 

The apex batch must call to a function in a class that will make a call out.

 

This is my trigger:

 

trigger ModAccountInvokeService on Account (after update) {
    List <Id> MainAccounts=new List <Id>();
    List <Id> BranchAccounts=new List <Id>();
    for (Integer i=0;i<Trigger.new.size();i++){
        Account acc=Trigger.new[i];
        if (acc.RecordTypeId=='012D000000035RH' || acc.RecordTypeId=='012D000000035Bw'){
            if (Trigger.new[i].Province_Commercial_2__c!=Trigger.old[i].Province_Commercial_2__c){
                //
                //myCallOuts.SyncMainAccount(acc.Id);
                //Introduce the Id of the account to the list
                MainAccounts.add(Trigger.new[i].Id);
            }
        
    }
    //Llamo a los batches que irán haciendo el call out
     Database.executeBatch(new MainAccountSynchBratch(MainAccounts),1);
}

 And this is my Batch Code:

 

global class MainAccountSynchBatch implements Database.Batchable<Id>,Database.AllowsCallouts{
    
    //Recibo el listado de las cuentas main que hay que sincronizar
    
	List<Id> MainAccounts = new List<Id>();
    global MainAccountSynchBatch(List<Id> listMainAccounts)
	{
        MainAccounts = listMainAccounts;
    }

    global List<Id> start(Database.BatchableContext BC)
	{
		//return DataBase.getQueryLocator([SELECT Id FROM account WHERE Id IN : MainAccounts]);
        return Database.Batchable();//(MainAcounts);
	}
	
    global void execute(Database.BatchableContext BC,List<Account> scopeAcc)
	{
		
        for (Integer i=0;i<scopeAcc.size();i++){
            //scopeAcc.get(i).Commercial_Area__c=ownerMap.get(scopeAcc.get(i).OwnerId).Commercial_Area__c;
            myCallOuts.SynchMainAccount(scopeAcc.get(i));
    	}
    	//update scopeAcc;
	}
    
    global void finish(Database.BatchableContext BC)
	{
    	//Send an email to the User after your batch completes
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
		String[] toAddresses = new String[] {'a.tejado@hotelbeds.com'};
		mail.setToAddresses(toAddresses);
		mail.setSubject('Apex Batch Synch Job is done');
		mail.setPlainTextBody('The batch Apex Synch job processed ');
		Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
	}

}

 How can I pass to the Execute method the list of Ids that I receive in the batch?

 

Really appreciate your help.

 

Thanks,

 

Antonio

I have a class which does HTTP callouts.  Because I am needing to do more than 10 callouts at a time, I am using a Batch class to call that class.  At this point, I can call that class without issue by directly calling the batch execute via system log.  The next step I need to do is put the Batch in a scheduler that runs every hour.  So I now have 4 classes:

 

1.) My original class that does the HTTP callouts

2.) The batch class which calls #1 scoped one record at a time to avoid the 10-callout limit

3.) A schedulable class which executes the batch class and has a method to invoke system.scheduler

 

But now I'm stuck because it seems no matter how I organize things, I get one of these errors:

 

1.) Future method cannot be called from a future method (I'm getting this one with my current code setup)

2.) You have uncommitted work pending (I get this one if the callout method isn't a future method)

3.) Too many callouts - 2 (I get this one if I make the callout method NOT a future method and somehow try to update the assets all together in the batch class)

 

What the heck am I supposed to do to get this class scheduled??  Below is my code.

 

Class #1: The HTTP Callout Class

global class VLStatus {

 

  @future(callout=true)
   global static void getMachineStatus(String asstId){

        Asset asst = new Asset();
        asst = [select id, name, SerialNumber from Asset where Id = :asstId];

 

       //code that does my callout stuff and sets the asset fields

      update asset;

  }

 

Class #2: The Batch Class

global class VLStatusBatch implements Database.Batchable<Asset>, Database.AllowsCallouts{

//Get list of machines that we are still waiting on for a response
Asset[] AssetsToUpdate = [Select id, name, SerialNumber from Asset where Pending_VL_Response__c = 1];

global Iterable<Asset> start(database.batchablecontext BC){
    return (AssetsToUpdate);    
}

global void execute(Database.BatchableContext BC, List<Asset> scope){
    for(Asset a : scope){
            VLStatus.getMachineStatus(a.Id);
    }    
}

global void finish(Database.BatchableContext info){
    }//global void finish loop

}

 

 

 

Class #3: The Schedulable Class

global class HourlyScheduler implements Schedulable{
    global HourlyScheduler (){}

    public static void start(){
        //Seconds Minutes Hours Day_of_month Month Day_of_week optional_year
        System.schedule('Pending Machine Status Update', '0 5 1-23 * * ?', New HourlyScheduler());

    }

    global void execute(SchedulableContext ctx){
        VLStatusBatch b = new VLStatusBatch();
        database.executebatch(b);    
    }
}