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
Lawrence Manfredi 24Lawrence Manfredi 24 

Unable to get information about an Apex batch job after it has run...

 I am trying to access additional information about a failed batch job. 

I read the doc at https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/asynch_api_batches_get_info_all.htm
The solution there is to build a URL to form a GET request to return information about a particular job.

Here is the general form of the URL:
https://instance_name—api.salesforce.com/services/async/APIversion/job/jobid/batch

So I then substituted the specifics of my org into this url, and the URL becomes 
https://NA##—api.salesforce.com/services/async/42/job/7071J00008J6XVu/batch (## is instance server)

This should take me to information about the batch. But it doesn't.
It redirects me to 
https://xn--na##api-516c.salesforce.com/services/async/42/job/7071J00008J6XVu/batch

And then I get the following error message in my web browser: 
"This site can’t be reached
xn--naXXapi-516c.salesforce.com’s server IP address could not be found.
Try running Network Diagnostics.
DNS_PROBE_FINISHED_NXDOMAIN"

No information about my batch job is provided.

What is this website?
I formed the URL correctly, so what is going wrong?

SF Support said I needed to access it via API, but the docs said a simple GET request shoudl return info...so what lightweight tool can i use to just get Apex batch info from a jobid?
{!pramod_nishane}{!pramod_nishane}
Hi Lawrence,

You can use option of sending mail in "finish" method  where you can send mail using  "Messaging.SingleEmailMessage" to the user who launched the batch code or whomever you want to report status of batch job.

global void finish(database.BatchableContext BC) {
Util.finishEmail(BC);
}

public static Messaging.SingleEmailMessage finishEmail(Database.BatchableContext BC){
    messaging.singleEmailMessage mail = new messaging.singleEmailMessage();
    AsyncApexJob a = [SELECT Id,
                             Status,
                             NumberOfErrors,
                             JobItemsProcessed,
                             TotalJobItems,
                             CompletedDate,
                             ExtendedStatus,
                             ApexClass.name,
                             CreatedBy.Email,
                             CreatedBy.Name
                      FROM AsyncApexJob 
                      WHERE Id =:BC.getJobId()];
    mail.setToAddresses(new string[]{a.CreatedBy.Email}); // whoever you want to report
    mail.setReplyTo('');   // Set the ReplyTo
    mail.setSubject('Batch Code Complete -- '+a.ApexClass.name);
    mail.setUseSignature(false);

    string td1='"border:1px solid green; width=200px;"';
    string td2='"width=200px; border:1px solid green; background-color:red; color:white; font-weight:bold;"';
    string tdHead='"border:1px solid green; width=200px; color:white; background-color:green; font-weight:bold;"';
    string ExtendedStatus='';
    if(a.ExtendedStatus!=null)
        ExtendedStatus=a.ExtendedStatus;
    string tdErrors=td1;
    if(a.NumberOfErrors>0)
        tdErrors=td2;
    string htmlBody = '<div style="border:2px solid green; border-radius:15px;"><p>Hi,</p><p><span style="color:brown; font-weight:bolder;">Salesforce</span> completed running <b>Apex Batch Code<>/b>.</p>'
    +'<p>Results:</p>'
    +'<center><table style="border:3px solid green; border-collapse:collapse;">'
    +'<tr><td style='+tdHead+'>Class Name</td><td style='+tdHead+'>'+a.ApexClass.name+'</td></tr>'
    +'<tr><td style='+td1+'>Completed Date</td><td style='+td1+'>'+a.CompletedDate+'</td></tr>'
    +'<tr><td style='+td1+'>Status</td><td style='+td1+'>'+a.Status+'</td></tr>'
    +'<tr><td style='+td1+'>Job Items Processed</td><td style='+td1+'>'+a.JobItemsProcessed+' / '+a.TotalJobItems+'</td></tr>'
    +'<tr><td style='+td1+'>NumberOfErrors</td><td style='+tdErrors+'>'+a.NumberOfErrors+'</td></tr>'
    +'<tr><td style='+td1+'>Extended Status</td><td style='+td1+'>'+ExtendedStatus+'</td></tr>'
    +'<tr><td style='+tdHead+'>Created By</td><td style='+tdHead+'>'+a.CreatedBy.Name+' ('+a.CreatedBy.Email+')</td></tr>'
    +'</table></center>'
    +'<p>Enjoy the <b>results</b>!</p><p><span style="font-family:"Courier New", Courier, monospace; color:green; font-weight:bold; font-size:larger;">Scott</span></p></div>';

    mail.setHtmlBody(htmlBody);
    return mail;
}

Let me know in case of any concerns.

Please mark this answer as the solution/ best answer if it solves your purpose so that it can help other community members.

Thanks,
Pramod Nishane
Salesforce Consultant
Varasi LLC
www.varasi.com
Lawrence Manfredi 24Lawrence Manfredi 24
OK so it really sounds like this has to be included in the code before the job runs. It's not something that is stored in SF and then could be queried later. Thanks!
{!pramod_nishane}{!pramod_nishane}
Hi Lawrence,

You can do that also storing batch job status/information in any custom object at the time of execution.
and later you can query whenever required.

but problem with that only is if you have lot of batch classes so you need to delete that data periodically.

Thanks,
Pramod Nishane
Salesforce Consultant
Varasi LLC
www.varasi.com