+ Start a Discussion
Tulasiram ChippalaTulasiram Chippala 

Need help in batch class : "Ending position out of Bounds: 32"

global class AccountIdGeneration implements Database.Batchable<sObject>,Database.Stateful{
    global String query ;
    List<Account> accountList = new List<Account>();
    global AccountIdGeneration(){
        query = 'Select id, Name, website from account where website != null';
    }
    global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext BC, List<account> scope){
        List<account> lstAccount = new List<account>(); 
        for(account acc : scope){
           lstAccount.add(acc);
            
        }
        accountList.addAll(lstAccount);
    }
    global void finish(Database.BatchableContext BC){
        String finalString = 'Generated Id, website, Account Id, Name \n';
        System.debug('--accountList Size---'+accountList.size());
        /*-------------------- Forming Excel String ---------------*/
        for(account acc : accountList){
            Blob cryptoKey = Blob.valueOf('abcdefghijklmnopqrstuvwxyzabcdef');
            // Converting website to blob
            Blob data = Blob.valueOf(acc.website);
            Blob encryptedData = Crypto.encryptWithManagedIV('AES256', cryptoKey, data);
            String encryptedDataStr = EncodingUtil.base64Encode(encryptedData); 
            String key = encryptedDataStr.replaceAll('[^a-zA-Z\\s]', '');
            String str = acc.website.SubStringBefore('.');
            String finalID = '';
            if(str.length() >= 4 ){ finalID = str.substring(0, 4).toUppercase()+key.substring(30, 32).toUppercase(); }
            else if(str.length() < 4 && str.length() == 3){ finalID = str.substring(0, 3).toUppercase() +key.substring(29, 32).toUppercase();} 
            else if (str.length() < 4 && str.length() == 2){ finalID = str.substring(0, 2).toUppercase()+key.substring(28, 32).toUppercase();} 
            else if (str.length() < 4 && str.length() == 1){ finalID = str.substring(0, 1).toUppercase()+key.substring(27, 32).toUppercase();} 
            String recordString = finalID+','+acc.website+','+ acc.id+','+acc.Name+'\n';
            finalString  =  finalString + recordString;    
            
        }
        System.debug('--finalString-'+finalString);
        /*-------------------- Forming Email ---------------*/
        
        Messaging.EmailFileAttachment attachmentFile = new Messaging.EmailFileAttachment();
        blob accountList = Blob.valueOf(finalString);
        string csvname= 'accListFile.csv';
        attachmentFile.setFileName(csvname);
        attachmentFile.setBody(accountList);
        Messaging.SingleEmailMessage email =new Messaging.SingleEmailMessage();
        String email1 = 'test@gmail.com';
        String[] toAddresses = new list<string> {email1};
            String subject ='Account Generated Id List';
        email.setSubject(subject);
        email.setToAddresses( toAddresses );
        email.setPlainTextBody('');
        email.setFileAttachments(new Messaging.EmailFileAttachment[]{attachmentFile});
        Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});
    }
}
We are using this code for generating a 6-bit id for an account. When executing, the Finish method is not sending any email. logs showing batch apex status as "Ending position out of Bounds: 32".

Note: I am processing more than 10k records.

Please help me with this. Thanks in advance.
 
Best Answer chosen by Tulasiram Chippala
SarvaniSarvani
Hi Tulsiram,

I have tested your code with an example account having website as 'www.google.com'. The variable str in your code will have www which is fine but the key value generated is having only 30 characters. So when the control comes inside the loop checking for str length equal to 3. The statement... finalID = str.substring(0, 3).toUppercase() +key.substring(29, 32).toUppercase(); is causing the error ending position out of bounds as the key has only 30 characters but trying to fetch 31,32. The same might happen with other if loops if key length is less than expected. Try adding condition for key legnth too in the loop like below if that makes sense:
if(str.length() >= 4  && key.length()>=32){ finalID = str.substring(0, 4).toUppercase()+key.substring(30, 32).toUppercase(); }
            else if(str.length() < 4 && str.length() == 3  && key.length()>=32){ finalID = str.substring(0, 3).toUppercase() +key.substring(29, 32).toUppercase();} 
            else if (str.length() < 4 && str.length() == 2  && key.length()>=32){ finalID = str.substring(0, 2).toUppercase()+key.substring(28, 32).toUppercase();} 
            else if (str.length() < 4 && str.length() == 1 && key.length()>=32){ finalID = str.substring(0, 1).toUppercase()+key.substring(27, 32).toUppercase();}
Hope this helps! Please mark as best if it solves your issue.

Thanks

All Answers

SarvaniSarvani
Hi Tulsiram,

I have tested your code with an example account having website as 'www.google.com'. The variable str in your code will have www which is fine but the key value generated is having only 30 characters. So when the control comes inside the loop checking for str length equal to 3. The statement... finalID = str.substring(0, 3).toUppercase() +key.substring(29, 32).toUppercase(); is causing the error ending position out of bounds as the key has only 30 characters but trying to fetch 31,32. The same might happen with other if loops if key length is less than expected. Try adding condition for key legnth too in the loop like below if that makes sense:
if(str.length() >= 4  && key.length()>=32){ finalID = str.substring(0, 4).toUppercase()+key.substring(30, 32).toUppercase(); }
            else if(str.length() < 4 && str.length() == 3  && key.length()>=32){ finalID = str.substring(0, 3).toUppercase() +key.substring(29, 32).toUppercase();} 
            else if (str.length() < 4 && str.length() == 2  && key.length()>=32){ finalID = str.substring(0, 2).toUppercase()+key.substring(28, 32).toUppercase();} 
            else if (str.length() < 4 && str.length() == 1 && key.length()>=32){ finalID = str.substring(0, 1).toUppercase()+key.substring(27, 32).toUppercase();}
Hope this helps! Please mark as best if it solves your issue.

Thanks
This was selected as the best answer
Tulasiram ChippalaTulasiram Chippala
Hi Sravani,

Thanks for your help.
I have tested your code with an example account having website as 'www.google.com'. The variable str in your code will have www

For the above point, we are storing the website as "google.com" only.
Tulasiram ChippalaTulasiram Chippala
key.substring(key.length()-2, key.length())

The above line helped me. But anyway your hint about the key size helped me.