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
Anindya ChattopadhyayAnindya Chattopadhyay 

Batch Apex with Selected Objects

Hi all:

I am a newbie to Salesforce and gradually getting the hang of it. One thing that I need to make use of soon is Batch Apex

We have got several opportunities on which we need to make calls to third party API to get back some result. This already works for individual Opportunity where we have got a button and with the click of the button, it calls the third party API for that Opportunity.

However we have now got a requirement where we can select several Opportunities together to make calls to third party API and get back the result for each. Batch Apex sounds like a good way to solve this problem. However being new to the Salesforce paltform, wondering what's the best way to achieve this.

Logically the steps are:

1. Select Opportunities which you need to process. May be build a collection of those Opprtunities.
2. Execute Batch Apex with the collection of Opportunities that have been built.

Just wondering what's the technical way to achieve this. In the start method of Batch Apex, I need to build the object scope with the selected Opportunities. How to achieve that?

Also when I am done with writing the Batch Apex class, how do I trigger the following:
Database.executeBatch(new <Class name>(), batch size);

to execute my Batch Apex?

Any help will be much appreciated.

Thanks
Anindya

Best Answer chosen by Anindya Chattopadhyay
Alba RivasAlba Rivas
Hi Anindya,

What you can do is to add a custom list view button that redirects to a visualforce page. That visualforce page will receive the selected records (its constructor has to receive a standardSetController). In that visualforce page, place a button that says, for example, "Continue and process the records". Make that button call a method that instantiates and launches the batch.

Eg: https://developer.salesforce.com/forums/?id=906F00000008ni4IAA

In that example, you should be calling the batch in "doSomething" method, and you have the selected records in "setCon.getSelected()". You can make your batch iterate over the records, or on the other hand extract their Ids, and pass them to the batch in the way I pointed to you before.

Regarding the limits: you could hit the max number of items on a collection limit, or a heap size limit if it is too big. 

If you are allowing somebody to select the opportunities on a list, I don't think you will quick those limits.

Hope that helps!

Regards.
 

All Answers

Alba RivasAlba Rivas
Hi Anindya,

If you need to process a big number of records, with no time constraints, batch apex will help you. 

The idea is that in the start method you can use a queryLocator or an iterator to retrieve the records you are going to process. Here (http://salesforce.stackexchange.com/questions/137443/what-is-the-iterable-interface-used-for-in-batch-apex/137448) you have some criteria for chosing one or another. 

If you are going to use a queryLocator, you have to pass a query to it, and it will query the records in chunks.

If you need to pass in a list of records, you could have an instance variable on your Batch Apex which holds the record Ids. Then, when you instantiate your batch apex, set the Ids before executing it.

Then, in the execute method, you will receive the queried records on each chunk:
public class MyBach implements Database.Batchable<sObject>{

     public Set<Id> myIds;

     public Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator([SELECT Name FROM Whatever__c WHERE Id IN: myIds]);
     }
     
     public void execute(Database.BatchableContext ctx, List<SObject> whateverRecords) {
         //...do whatever over the received records, async, in chunks of 200 by default
     }

     ...
}
To call the batch:
MyBatch mb = new MyBatch();
mb.myIds = ...
Database.executeBatch(mb);
I don't know the exact details of your use case, but be careful with myIds set. If this set is too big, you can hit limits.

Here you have the documentation: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_batch_interface.htm

Regards.
Anindya ChattopadhyayAnindya Chattopadhyay

Hi Alba:
 
Thanks for the reply. I got a good idea. Just few more queries:

1. How will I go on building the mb instance of the MfyBatch class? That's the first thing I need to do in this process.

We have got a view page for Opportunuties which lists all the current Opportunities. From there, how will I go and build this variable? Just an idea of the flow would be helpful.

2. What's the limit on myIds set? I reckon you mean maximum number of Ids in the collection.

3. Where exactly do you write this code?

MyBatch mb = new MyBatch();
mb.myIds = ...
Database.executeBatch(mb);

One way is to use developer console. But for us as end users need to execute this job, wondering what's the best way to process it?

Any help will be much appreciated.

Regards,
Anindya



 

YogeshMoreYogeshMore
Hi Anindya,

It is very simple to get selected opportunities in batch class. Follow the following steps.
 
  • Create batch class like-
    global class batchClassForAPI implements Database.Batchable<sObject>, Database.Stateful {
    
        private List<String> lstOfOppId;
    
        public batchClassForAPI(List<String> lstOfOppId1) {
            lstOfOppId = lstOfOppId1;
        }
    
        global Database.QueryLocator start(Database.BatchableContext BC) {
            String query = 'select id,Name from opportunity where Id IN: lstOfOppId';
            return Database.getQueryLocator(query);
        }
    
        global void execute(Database.BatchableContext BC, List<opportunity> scope) {
            system.debug('==========check====='+lstOfOppId);    
        }   
    
        global void finish(Database.BatchableContext BC) {
        }
    }
  • When you are selecting multiple opportunity and clicking on button then call above batch class like –
        List<String> lstOfString = new List<String>();
    	lstOfString.add(oppId_1);
    	lstOfString.add(oppId_2);
    	lstOfString.add(oppId_3);
    
        batchClassForAPI  shn = new batchClassForAPI(lstOfString);// Batch class parameterized constructor will call .
        database.executeBatch(shn,200);
like this way you can get selected opportunities in batch class.

Regards,
Yogesh More
more.yogesh422@gmail.com || Skype:-yogesh.more44
Alba RivasAlba Rivas
Hi Anindya,

What you can do is to add a custom list view button that redirects to a visualforce page. That visualforce page will receive the selected records (its constructor has to receive a standardSetController). In that visualforce page, place a button that says, for example, "Continue and process the records". Make that button call a method that instantiates and launches the batch.

Eg: https://developer.salesforce.com/forums/?id=906F00000008ni4IAA

In that example, you should be calling the batch in "doSomething" method, and you have the selected records in "setCon.getSelected()". You can make your batch iterate over the records, or on the other hand extract their Ids, and pass them to the batch in the way I pointed to you before.

Regarding the limits: you could hit the max number of items on a collection limit, or a heap size limit if it is too big. 

If you are allowing somebody to select the opportunities on a list, I don't think you will quick those limits.

Hope that helps!

Regards.
 
This was selected as the best answer
Anindya ChattopadhyayAnindya Chattopadhyay

Hi Alba/Yogesh:

Thanks for your replies. That was really helpful. But I am still stuck with something: How do I select multiple records on Opportunities page. I reckon I found out the reason why !!

We are using lightning experience and not the classic anymore. In classic you can select multiple records as shown below:

ce

In lightning, I can't even see that option to select multiple records as shown below:

le

I think once I am able to select multiple records I can go on creating the custom list view button, visual force page and then the Batch Apex.

Hope I made sense. So is there any way I can select multiple records using lightning experience?

Thanks and regards,
Anindya

 

Alba RivasAlba Rivas
Oh! I understand, I was thinking in classic, sorry. 

There is an idea for supporting multiselect on Lightning Experience: https://success.salesforce.com/ideaView?id=0873A000000PTlFQAW

But that's not possible yet :(

Possible solutions I can think of are:

- Implementing your own visualforce page that shows a custom selectable list view. Something like this: https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_quick_start_massupdate.htm

- Try to do the same but using apex:enhancedList visualforce component: https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_compref_enhancedList.htm - Not sure if this component will be selectable in Lightning Experience, but you can check!

- Try to do something similar in a Lightning Component -  I warn you that Salesforce hasn't released a standard listview component yet, and you have to create it from scratch: http://salesforce.stackexchange.com/questions/156920/list-view-for-custom-lightning-component

Regards.



 
Alba RivasAlba Rivas
Ey, I have done some tests, and I have found how to do it. When you create the list view button, you have to indicate it's multi record:

User-added image

Then navigate to "All" listview (it won't appear in the recent tab). 

I think the idea then it's a bit outdated, or was related to "Recent" listview, as this works in Lightning Experience.

Regards
Anindya ChattopadhyayAnindya Chattopadhyay
Hi Alba:
So you mean the steps are as follows:

1. Create a custom list view button with the content source as visual force page and multi record selection enabled.
2. Then navigate to All listview for Opportunities.
3. Select multiple Opportunities and click on the custom list view button. The process then flows as mentioned above. 

Am I right?

However I am having a weird problem that I can't select any VisualForce page while I am creating that custom list view button! A screenshot is given below.

User-added image

The Content dropdown is empty. I have got several VisualForce pages thought.

Thanks and regards,
Anindya
Alba RivasAlba Rivas
Yes, that's the order. You have to place the button in the list view layout as well between steps 1 and 2.

That is happening to you because you need to have a visualforce page that is able of managing a list of records:
 
<apex:page standardController="Opportunity" recordSetVar="oppty" extensions="OpptyController">
    ... 
</apex:page>

And then the controller should handle a standardSetController:
 
public with sharing class OpptyController {

    public OpptyController(ApexPages.StandardSetController controller){ 
        List<Opportunity> opptys = (List<Contact>)controller.getSelected(); 
          // ...Here you could call a method that launches your batch process
    }
}

Then the page will appear.
Anindya ChattopadhyayAnindya Chattopadhyay
Thanks heaps. I will give it a go. So the final steps are:

1. Create a custom list view button with the content source as visual force page and multi record selection enabled.
2. Include the  button in the list view layout.
2. Then navigate to All listview for Opportunities.
3. Select multiple Opportunities and click on the custom list view button. The process then flows as mentioned above. 

Cheers!