8/31/2012     Using Batch Jobs to Improve         the User Experience              Safe HarborIve always said to anyone th...
8/31/2012 A developer can now employ batch Apex to build complex, long-running processes on the Force.com platform.       ...
8/31/2012            Scenario 1• 324,476 Accounts• 142,105 Opportunity records• 1 NEW record type       Administrative Use...
8/31/2012      Developer Objects• Batch Process(es)• Something to fire it  – Trigger  – Schedule  – VisualForce Page• Test...
8/31/2012                                 APEX Codeglobal class BatchOppLineZero implements Database.Batchable<SObject> { ...
8/31/2012                           APEX CodeExecute Methodglobal void execute(Database.BatchableContext ctx, List<Sobject...
8/31/2012                    Execute Method – scenario 1global void execute(Database.BatchableContext ctx, List<Sobject> s...
8/31/2012                                  APEX CodeFinish Methodglobal void finish(Database.BatchableContext ctx){    Asy...
8/31/2012 Governor (and other) Limits• 5 active jobs• Can’t call a batch from a batch• 1M lines of code, 250k daily batche...
8/31/2012            Why Not Real Time?• External processing     – Third party updates     – Delivery Status• Just in time...
8/31/2012                                APEX Code    global void finish(Database.BatchableContext ctx){     *     *     *...
8/31/2012  Better User Experience• Asynchronous Triggers• Improved data quality  – Enrichment  – Cleansing• Don’t make the...
8/31/2012  Questions?   Mike Melnickmikem@asktwice.com   770-329-3664                           13
Upcoming SlideShare
Loading in …5
×

Salesforce Batch processing - Atlanta SFUG

2,414 views

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,414
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
68
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Salesforce Batch processing - Atlanta SFUG

  1. 1. 8/31/2012 Using Batch Jobs to Improve the User Experience Safe HarborIve always said to anyone that will listen to me(which is not very many) that software is an artform. It attracts artists.Just look at any software company and theamount of musicians, artists, carpenters, etc…working there that create code for a living andcreate other things in their down time. - Steve Lacey 1
  2. 2. 8/31/2012 A developer can now employ batch Apex to build complex, long-running processes on the Force.com platform. - Force.com Apex Code Developers GuideComplex, Long Running tasks• Pre or Post processing tasks• Account reassignments• Price book updates• Custom or Transactional ObjectsGovernor Limits are Your Friends … 2
  3. 3. 8/31/2012 Scenario 1• 324,476 Accounts• 142,105 Opportunity records• 1 NEW record type Administrative Use• Nulling out a field• Arghhhh!!!!! 3
  4. 4. 8/31/2012 Developer Objects• Batch Process(es)• Something to fire it – Trigger – Schedule – VisualForce Page• Test Class Batch Process• Start – Define the records to process• Execute – “Long, Complex…”• Finish – Post processing – e-Mail status – Schedule a repeat job, etc 4
  5. 5. 8/31/2012 APEX Codeglobal class BatchOppLineZero implements Database.Batchable<SObject> { global final string query; global boolean process_on; List<OpportunityLineItemSchedule> schList = new List<OpportunityLineItemSchedule> (); private string query1 = Select Id, scheduledate, revenue from OpportunityLineItemSchedule; global BatchOppLineZero () { if (system.Test.isRunningTest()) { this.query = query1 + where scheduledate >= :chkDate; } else { this.query = query1 + where scheduledate >= :testDate; } }** APEX Code Start Method global Database.queryLocator start(Database.BatchableContext ctx){ Date myDate = date.today(); Date chkDate = date.newinstance (mydate.year(),mydate.month(),1).addmonths(-3); return Database.getQueryLocator(query); } 5
  6. 6. 8/31/2012 APEX CodeExecute Methodglobal void execute(Database.BatchableContext ctx, List<Sobject> scope){ schList = (List<OpportunityLineItemSchedule>)scope; for (OpportunityLineItemSchedule lis:schList) lis.revenue=0; update schList; } Scenario 1 n opportunity records need to be updated • Record type needs to be changed • OwnerId updated – Should be the account owner – Default for account location if owner is inactive • Opportunity type should reflect account property 6
  7. 7. 8/31/2012 Execute Method – scenario 1global void execute(Database.BatchableContext ctx, List<Sobject> scope){ oppUpdate = (List<Opportunity>)scope; List<Account> accList = new List<Account>(); Set<Id> accId = new set<id>(); ID recTypeId; List<RecordType> recList = new List<RecordType> ([Select Id, Name from RecordType]); for (RecordType rec:recList) if (rec.name==Ad Revenue) recTypeId=rec.id; ID pitOwnerID, denOwnerID, laxOwnerID; List<User> repList = [Select ID, name, Property__c, IsActive, Sales_id__c from User]; MAP<string,User> repMap = new MAP<string,User>(); MAP<Id,User> repActiveMap = new MAP<Id,User>(); for (User u:repList) { repMap.put(u.UserNumber__c,u); repActiveMap.put(u.id,u); if (u.name == ‘PIT Owner) pitOwnerID=u.id; if (u.name == ‘DEN Owner) denOwnerID=u.id; if (u.name == ‘LAX Owner) laxOwnerID=u.id; } for(Opportunity o:oppUpdate) accId.add(o.accountid); Map<Id,Account> accMap = new Map<Id,Account> ( [Select Id, ownerid, property__c from Account where id in: accId]); for (Opportunity o:oppUpdate){ o.description = This opportunity is used to track Ordered Ad Revenue; Account acc=accMap.get(o.accountid); if (acc !=null) { o.Opportunity_Type__c = acc.Property__c; User rep = repActiveMap.get(acc.ownerid); if (rep.IsActive) { acc.ownerid = rep.id; } else { if (acc.property__c == ‘PIT && pitOwnerId !=null) o.ownerid = pitownerid; if (acc.property__c == ‘DEN && denOwnerId !=null) o.ownerid = denownerid; if (acc.property__c == ‘LAX && laxOwnerId !=null) o.ownerid = laxownerid; } if (recTypeId !=null) o.RecordTypeId = recTypeId; } } update oppUpdate; } 7
  8. 8. 8/31/2012 APEX CodeFinish Methodglobal void finish(Database.BatchableContext ctx){ AsyncApexJob a = [SELECT id, ApexClassId, JobItemsProcessed, TotalJobItems, NumberOfErrors, CreatedBy.Email FROM AsyncApexJob WHERE id = :ctx.getJobId()]; string emailMessage = We executed + a.totalJobItems + batches.; Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); String[] toAddresses = new String[] {a.createdBy.email}; mail.setToAddresses(toAddresses); mail.setReplyTo(noreply@salesforce.com); mail.setSenderDisplayName(Batch Job Summary); mail.setSubject(Opportunity batch update complete); mail.setPlainTextBody(emailMessage); mail.setHtmlBody(emailMessage); Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail }); }} Testing your Batch @ISTest public with sharing class TESTBatchOppLineZero { static testMethod void TESTBatchOppLineZero() { List<Account> actList = new List<Account>(); * * Test.startTest(); Database.executeBatch(new BatchOppLineZero()); Test.stopTest(); system.assertEquals(…..) } } 8
  9. 9. 8/31/2012 Governor (and other) Limits• 5 active jobs• Can’t call a batch from a batch• 1M lines of code, 250k daily batches, 10k DML statements• “One at a time”• Subject to available resources• Check the docs Scheduled Jobs• After hours processing• Daily / weekly / monthly jobs• Asynchronous triggers• Future jobs 9
  10. 10. 8/31/2012 Why Not Real Time?• External processing – Third party updates – Delivery Status• Just in time• Balance resources• Look at the business and its needs APEX Codeglobal class BatchStageImportScheduler implements Schedulable { global void execute (SchedulableContext ctx) { BatchStageImport batchImport = new BatchStageImport(); ID batchprocessid = Database.executeBatch(batchImport); }} 10
  11. 11. 8/31/2012 APEX Code global void finish(Database.BatchableContext ctx){ * * * // Schedule a job for 5 am tomorrow… Datetime sysTime = System.now(); sysTime = sysTime.addDays(1); String chron_exp = + 0 + + 0 + + 5 + + sysTime.day() + + sysTime.month() + ? + sysTime.year(); BatchStageImportScheduler BatchSched = new BatchStageImportScheduler(); // Schedule the next job, and give it the system time so name is unique System.schedule(BatchStageImport + sysTime.getTime(),chron_exp,BatchSched); }} Monitoring Jobs • Check status • Cancel jobs • Error(s) Your name -> Setup -> (Administration Setup) Monitoring -> Apex Jobs (or) Scheduled Jobs 11
  12. 12. 8/31/2012 Better User Experience• Asynchronous Triggers• Improved data quality – Enrichment – Cleansing• Don’t make the customer wait Next Steps• Investigate the Business Rules – Maybe this is not for you• Make sure you test• Don’t make the customer wait 12
  13. 13. 8/31/2012 Questions? Mike Melnickmikem@asktwice.com 770-329-3664 13

×