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
kevin_carkevin_car 

Another @future question - sorry

 

Hi,
Well, right on the heels of "Man"ish's question, here I am with an @future question...

I read that it's possible to schedule a report to run using @future with an HTTP callout, but I'm having absolutely no luck. Hoping someone has Ideas. All of the below seems to work, but I neve get the results emailed to me.

The email address and the report ID are stored in a Custom settings group down in the Exporter class...

 

The anonymous Apex:

 String s = '1 04 19 24 1 ?'; 
 Exporter  abc = new Exporter ();
 system.schedule('Report Job', s, abc);

 

The Schedulable class:

global class ReportExporter implements System.Schedulable {
    global void execute(SchedulableContext sc) {
    getmailReportOutput gem = new getmailReportOutput();
    gem.runReport();
    }
}

 

The class that does te HTTP callout to the  VF page that calls the class that generates and emails the report:

public class getmailReportOutput{
    
    public getmailReportOutput() {
        }
    
    public void runReport() {
        makeReportRequest();
        }
        
@future (callout=true)      
    public static void makeReportRequest()  {   
        ReportName__c mc = ReportName__c.getValues('ReportName');
        String strEmailAddr =  mc.RptEmail__c;
        URL xHost = System.URL.getSalesforceBaseUrl();
        String strHost =xHost.getHost();
        String requestUrl =  'https://' + strHost + '/apex/TestSendReport';
        HttpRequest req = new HttpRequest();
        req.setEndpoint(requestUrl);
        req.setMethod('GET');
        req.setHeader('Cookie','sid=' + UserInfo.getSessionId());
        String output = new Http().send(req).getBody();
        }
    }
    

 

The VF page that calls the class that generates the report and emails the CSV file:

<apex:page controller="Exporter" action="{!executeRpt}">
  <!-- Begin Default Content REMOVE THIS -->  
  <!-- End Default Content REMOVE THIS -->
</apex:page>

 

...And lastly, the class that does the actual work of generating the results and emailing them off:

 

public class Exporter {
    public static Boolean isTest;
    public static String strEmailAddr;
    
    void Exporter() {
        isTest = false;
        }
    
    public void execute    () {
        getmailReportOutput gem = new getmailReportOutput();
        gem.runReport();
        }
        
    public void setSendRpt(String locEmailAddr) {  
        isTest = false;
        strEmailAddr =  locEmailAddr;
        }
  
   public void setTest() {
        isTest = true;
        }

    public PageReference runThisPage() {
        ApexPages.PageReference report = new ApexPages.PageReference('/apex/TestSendReport');
        return report.setRedirect(false);
        }
        
             
    public void executeRpt() {
        System.debug('CALLING REPORT EXPORTER...');        
        ReportName__c mc = ReportName__c.getValues('ReportName');
        strEmailAddr =  mc.RptEmail__c;
        
        System.debug('ReportName:' +  mc.RptName__c);
        System.debug('EmailAddr:' + mc.RptEmail__c);
        integer a = 1;
        ApexPages.PageReference report = new ApexPages.PageReference( '/' + mc.RptName__c + '?csv=1');
         
        Messaging.EmailFileAttachment attachment = new Messaging.EmailFileAttachment();
        attachment.setFileName('report.csv');
        attachment.setBody(report.getContent());
        attachment.setContentType('text/csv');
        Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
        message.setFileAttachments(new Messaging.EmailFileAttachment[] { attachment } );
        message.setSubject('Report');
        message.setPlainTextBody('The report is attached.');
        message.setToAddresses( new String[] { strEmailAddr } );
        Messaging.sendEmail( new Messaging.SingleEmailMessage[] { message } );        
    }
 
}

 

If I just call the page, it all works great- all I ned to do is figure out how to schedule the page... but no luck.

 

Any help is appreciated.

 

Thanks

 

 

 

 

 

 

 

 

 

 

kiranmutturukiranmutturu

i didn't get what is meant by scheduling a page means in your statement? you can't schedule a page but you can schedule a controller..i think u can schedule ReportExporter class with out the functionality of the visualforce page..

 

kevin_carkevin_car

Hi Kiran,

 

When I call reportExporter directly, I get a message saying that I can't call the getContent directly.  That's why I'm going through all these gyrations.

 

My schedulable class getmailReportOutput  is actuall doing an HTTP callout to a VF page from an @future clause.

I'm scheduling this from the ReportExporter class.

 

Also, as you can tell, the "scheduled" VF page basically calls a controller method called "{!executeRpt}" that builds a CSV file and sends it to the email recipient via a lookup on a custom settings entry.

 

As you can tell, I'm trying to get quite creative with a solution for this... It seems to all work, in that I don't get any error messages from the debug console, and I do get an HTTP response from the VF page of 200 - I just never get the email with the CSV (I don't get any email).   It's strange.

 

Thanks for any help.

 

EDIT:

Oh, I also set up the site :http://cs(n).visual.force.com as a remote site in the security settings - seems like that was necessary as I got an error in the debug console about that during the iteration of developing this.

 

 EDIT 2:

Looking at the debug log, I see this snippet:

09:19:01.418 (418984000)|SYSTEM_METHOD_ENTRY|[23]|System.debug(ANY)
09:19:01.419 (419055000)|USER_DEBUG|[23]|DEBUG|HTTP RESPONSE RETURNED: <script>
var escapedHash = '';
var url = 'https://test.salesforce.com/?ec=302&startURL=%2Fapex%2FTestSendReport';
if (window.location.hash) {
   escapedHash = '%23' + window.location.hash.slice(1);
}
if (window.location.replace){ 
window.location.replace(url + escapedHash);
} else {;
window.location.href = url + escapedHash;
} 
</script>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

 

 

...  is this significant? Further - I get another debug log that seems to say that the report was generated, with the csv attachment and sent to me with no problem.  Heres the log...

27.0 APEX_CODE,FINEST;APEX_PROFILING,INFO;CALLOUT,INFO;DB,INFO;SYSTEM,DEBUG;VALIDATION,INFO;VISUALFORCE,INFO;WORKFLOW,INFO
09:38:36.303 (303605000)|EXECUTION_STARTED
09:38:36.303 (303665000)|CODE_UNIT_STARTED|[EXTERNAL]|066P00000008yb8|VF: /apex/TestSendReport
09:38:36.305 (305060000)|CODE_UNIT_STARTED|[EXTERNAL]|01pP0000000DlLl|Exporter <init>
09:38:36.305 (305077000)|SYSTEM_MODE_ENTER|true
09:38:36.305 (305682000)|VARIABLE_SCOPE_BEGIN|[2]|Exporter.isTest|Boolean|false|true
09:38:36.305 (305708000)|VARIABLE_SCOPE_BEGIN|[3]|Exporter.strEmailAddr|String|false|true
09:38:36.306 (306327000)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:15
09:38:36.306 (306345000)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:8
09:38:36.306 (306372000)|METHOD_ENTRY|[1]|01pP0000000DlLl|Exporter.Exporter()
09:38:36.306 (306384000)|STATEMENT_EXECUTE|[1]
09:38:36.306 (306394000)|STATEMENT_EXECUTE|[1]
09:38:36.306 (306403000)|METHOD_EXIT|[1]|Exporter
09:38:36.306 (306423000)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:4
09:38:36.306 (306441000)|VARIABLE_SCOPE_BEGIN|[1]|this|Exporter|true|false
09:38:36.306 (306511000)|VARIABLE_ASSIGNMENT|[1]|this|{}|0x16d8f5e4
09:38:36.306 (306530000)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:1
09:38:36.306 (306567000)|VARIABLE_SCOPE_BEGIN|[2]|this|system.ApexBaseClass|true|false
09:38:36.306 (306609000)|VARIABLE_ASSIGNMENT|[2]|this|{}|0x16d8f5e4
09:38:36.306 (306631000)|STATEMENT_EXECUTE|[1]
09:38:36.306 (306648000)|CODE_UNIT_FINISHED|Exporter <init>
09:38:36.306 (306707000)|CODE_UNIT_STARTED|[EXTERNAL]|01pP0000000DlLl|Exporter invoke(executeRpt)
09:38:36.306 (306753000)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:4
09:38:36.306 (306771000)|VARIABLE_SCOPE_BEGIN|[30]|this|Exporter|true|false
09:38:36.306 (306812000)|VARIABLE_ASSIGNMENT|[30]|this|{}|0x16d8f5e4
09:38:36.306 (306834000)|STATEMENT_EXECUTE|[30]
09:38:36.306 (306841000)|STATEMENT_EXECUTE|[31]
09:38:36.306 (306884000)|HEAP_ALLOCATE|[31]|Bytes:26
09:38:36.307 (307021000)|SYSTEM_METHOD_ENTRY|[31]|System.debug(ANY)
09:38:36.307 (307057000)|USER_DEBUG|[31]|DEBUG|CALLING REPORT EXPORTER...
09:38:36.307 (307067000)|SYSTEM_METHOD_EXIT|[31]|System.debug(ANY)
09:38:36.307 (307078000)|STATEMENT_EXECUTE|[32]
09:38:36.307 (307089000)|HEAP_ALLOCATE|[32]|Bytes:10
09:38:36.307 (307264000)|SYSTEM_METHOD_ENTRY|[32]|ReportName__c.getValues(String)
09:38:36.308 (308279000)|HEAP_ALLOCATE|[32]|Bytes:48
09:38:36.308 (308301000)|SYSTEM_METHOD_EXIT|[32]|ReportName__c.getValues(String)
09:38:36.308 (308315000)|VARIABLE_SCOPE_BEGIN|[32]|mc|ReportName__c|true|false
09:38:36.308 (308551000)|VARIABLE_ASSIGNMENT|[32]|mc|{"serId":1,"value":{"Name":"ReportName","SetupOwnerId":"00DP00000007CFaMAM","RptName__c":"00OP0000000Jp3N","LastModifiedById":"00500000006w214AAA","SystemModstamp":"2013-01-24T19:50:17.000Z","CreatedById":"00500000006w214AAA","RptEmail__c":"kevin.carothers@city (13 more) ...","CreatedDate":"2013-01-24T01:04:12.000Z","IsDeleted":false,"LastModifiedDate":"2013-01-24T19:50:17.000Z","Id":"a0LP0000005FKc4MAG"}}|0x77cda7ca
09:38:36.308 (308570000)|STATEMENT_EXECUTE|[33]
09:38:36.308 (308632000)|VARIABLE_ASSIGNMENT|[33]|Exporter.strEmailAddr|"kevin.carothers@city (13 more) ..."
09:38:36.308 (308644000)|STATEMENT_EXECUTE|[35]
09:38:36.308 (308655000)|HEAP_ALLOCATE|[35]|Bytes:11
09:38:36.308 (308695000)|HEAP_ALLOCATE|[35]|Bytes:26
09:38:36.308 (308712000)|SYSTEM_METHOD_ENTRY|[35]|System.debug(ANY)
09:38:36.308 (308736000)|USER_DEBUG|[35]|DEBUG|ReportName:00OP0000000Jp3N
09:38:36.308 (308745000)|SYSTEM_METHOD_EXIT|[35]|System.debug(ANY)
09:38:36.308 (308755000)|STATEMENT_EXECUTE|[36]
09:38:36.308 (308766000)|HEAP_ALLOCATE|[36]|Bytes:10
09:38:36.308 (308783000)|HEAP_ALLOCATE|[36]|Bytes:43
09:38:36.308 (308796000)|SYSTEM_METHOD_ENTRY|[36]|System.debug(ANY)
09:38:36.308 (308817000)|USER_DEBUG|[36]|DEBUG|EmailAddr:kevin.carothers@citymedia.com
09:38:36.308 (308825000)|SYSTEM_METHOD_EXIT|[36]|System.debug(ANY)
09:38:36.308 (308835000)|STATEMENT_EXECUTE|[37]
09:38:36.308 (308854000)|VARIABLE_SCOPE_BEGIN|[37]|a|Integer|false|false
09:38:36.308 (308861000)|HEAP_ALLOCATE|[37]|Bytes:4
09:38:36.308 (308885000)|VARIABLE_ASSIGNMENT|[37]|a|1
09:38:36.308 (308895000)|STATEMENT_EXECUTE|[42]
09:38:36.308 (308913000)|HEAP_ALLOCATE|[42]|Bytes:1
09:38:36.308 (308930000)|HEAP_ALLOCATE|[42]|Bytes:16
09:38:36.308 (308940000)|HEAP_ALLOCATE|[42]|Bytes:6
09:38:36.308 (308950000)|HEAP_ALLOCATE|[42]|Bytes:22
09:38:36.309 (309019000)|VARIABLE_SCOPE_BEGIN|[42]|report|System.PageReference|true|false
09:38:36.309 (309153000)|VARIABLE_ASSIGNMENT|[42]|report|"/00OP0000000Jp3N?csv=1"|0x5ede6433
09:38:36.309 (309170000)|STATEMENT_EXECUTE|[45]
09:38:36.310 (310416000)|VARIABLE_SCOPE_BEGIN|[45]|attachment|Messaging.EmailFileAttachment|true|false
09:38:36.310 (310654000)|VARIABLE_ASSIGNMENT|[45]|attachment|"common.api.soap.wsdl.EmailFileAttachment@5a8480ed"|0x312c7608
09:38:36.310 (310671000)|STATEMENT_EXECUTE|[46]
09:38:36.310 (310683000)|HEAP_ALLOCATE|[46]|Bytes:10
09:38:36.310 (310743000)|STATEMENT_EXECUTE|[48]
09:38:36.310 (310769000)|SYSTEM_METHOD_ENTRY|[48]|System.PageReference.getContent()
09:38:40.061 (4061179000)|SYSTEM_METHOD_EXIT|[48]|System.PageReference.getContent()
09:38:40.061 (4061307000)|STATEMENT_EXECUTE|[53]
09:38:40.061 (4061332000)|HEAP_ALLOCATE|[53]|Bytes:8
09:38:40.061 (4061396000)|STATEMENT_EXECUTE|[54]
09:38:40.062 (4062321000)|VARIABLE_SCOPE_BEGIN|[54]|message|Messaging.SingleEmailMessage|true|false
09:38:40.062 (4062508000)|VARIABLE_ASSIGNMENT|[54]|message|"common.api.soap.wsdl.SingleEmailMessage@5605f541"|0x2128aa86
09:38:40.062 (4062525000)|STATEMENT_EXECUTE|[55]
09:38:40.062 (4062644000)|HEAP_ALLOCATE|[55]|Bytes:4
09:38:40.062 (4062722000)|SYSTEM_CONSTRUCTOR_ENTRY|[55]|<init>()
09:38:40.062 (4062778000)|SYSTEM_CONSTRUCTOR_EXIT|[55]|<init>()
09:38:40.062 (4062818000)|SYSTEM_METHOD_ENTRY|[55]|LIST<Messaging.EmailFileAttachment>.add(Object)
09:38:40.062 (4062836000)|SYSTEM_METHOD_EXIT|[55]|LIST<Messaging.EmailFileAttachment>.add(Object)
09:38:40.063 (4063046000)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:8
09:38:40.063 (4063089000)|STATEMENT_EXECUTE|[56]
09:38:40.063 (4063103000)|HEAP_ALLOCATE|[56]|Bytes:6
09:38:40.063 (4063147000)|STATEMENT_EXECUTE|[57]
09:38:40.063 (4063160000)|HEAP_ALLOCATE|[57]|Bytes:23
09:38:40.063 (4063192000)|STATEMENT_EXECUTE|[58]
09:38:40.063 (4063211000)|HEAP_ALLOCATE|[58]|Bytes:4
09:38:40.063 (4063228000)|SYSTEM_CONSTRUCTOR_ENTRY|[58]|<init>()
09:38:40.063 (4063255000)|SYSTEM_CONSTRUCTOR_EXIT|[58]|<init>()
09:38:40.063 (4063281000)|SYSTEM_METHOD_ENTRY|[58]|LIST<String>.add(Object)
09:38:40.063 (4063296000)|SYSTEM_METHOD_EXIT|[58]|LIST<String>.add(Object)
09:38:40.063 (4063345000)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:8
09:38:40.063 (4063372000)|STATEMENT_EXECUTE|[59]
09:38:40.063 (4063413000)|HEAP_ALLOCATE|[59]|Bytes:4
09:38:40.063 (4063462000)|SYSTEM_CONSTRUCTOR_ENTRY|[59]|<init>()
09:38:40.063 (4063493000)|SYSTEM_CONSTRUCTOR_EXIT|[59]|<init>()
09:38:40.063 (4063513000)|SYSTEM_METHOD_ENTRY|[59]|LIST<Messaging.SingleEmailMessage>.add(Object)
09:38:40.063 (4063528000)|SYSTEM_METHOD_EXIT|[59]|LIST<Messaging.SingleEmailMessage>.add(Object)
09:38:40.063 (4063570000)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:8
09:38:40.063 (4063591000)|SYSTEM_METHOD_ENTRY|[59]|Messaging.sendEmail(LIST<Messaging.Email>)
09:38:40.063 (4063704000)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:8
09:38:40.095 (4095751000)|EMAIL_QUEUE|[59]|subject: Report, bccSender: false, saveAsActivity: true, useSignature: true, toAddresses: [kevin.carothers@citymedia.com], plainTextBody: The report is attached., 
09:38:40.095 (4095970000)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:8
09:38:40.095 (4095995000)|SYSTEM_METHOD_EXIT|[59]|Messaging.sendEmail(LIST<Messaging.Email>)
09:38:40.223 (4223309000)|CODE_UNIT_FINISHED|Exporter invoke(executeRpt)
09:38:40.224 (4224422000)|VF_APEX_CALL|j_id0|{!executeRpt}|PageReference: none
09:38:40.553 (4335699000)|CUMULATIVE_LIMIT_USAGE
09:38:40.553|LIMIT_USAGE_FOR_NS|(default)|
  Number of SOQL queries: 0 out of 100
  Number of query rows: 0 out of 50000
  Number of SOSL queries: 0 out of 20
  Number of DML statements: 0 out of 150
  Number of DML rows: 0 out of 10000
  Number of code statements: 17 out of 200000
  Maximum heap size: 0 out of 6000000
  Number of callouts: 0 out of 10
  Number of Email Invocations: 1 out of 10
  Number of fields describes: 0 out of 100
  Number of record type describes: 0 out of 100
  Number of child relationships describes: 0 out of 100
  Number of picklist describes: 0 out of 100
  Number of future calls: 0 out of 10

09:38:40.553|CUMULATIVE_LIMIT_USAGE_END

09:38:40.335 (4335749000)|CODE_UNIT_FINISHED|VF: /apex/TestSendReport
09:38:40.335 (4335762000)|EXECUTION_FINISHED

 

Am I reading something wrong?

 

sf_evolutionsf_evolution

Hi Again Kiran,

 

Just to clarify, the reason I'm taking this approach is that I can't call getContent() from a schedulable context.

 

So I'm trying to take it out of that context, and put it in the @future context, via an HTTP callout - hence, the scheduling of the VF page... and the page just calls the report link and ships the CSV content off to an email address it looks up from the custom settings.

 

I know it sounds wonky, but it was the only thing I could  think of.   I'm still having trouble with it, but I don't think I'm the only one :-)

 

 

sf_evolutionsf_evolution

Sorry to keep bugging you Kiran-

I took your advice and took out the scheduling of the Apex page.

Now it's just a plain class schedule:

 

The Scheduled class:

global class ReportExporter implements System.Schedulable {
    global void execute(SchedulableContext sc) {
        getmailReportOutput gem = new getmailReportOutput();
        gem.runReport();
    }
}

 

The report  output class:

public class getmailReportOutput{
    
    public Static String strSessionID;
    
    public getmailReportOutput() {
        }
    
    public void runReport() {
        callAReport();
        }
@future 
    public static void callAReport()  { 
        Exporter exp = new Exporter ();
        PageReference pr = exp.runThisPage();
        }            
    }

 

And the report generator:

 


    public PageReference runThisPage() {
        ApexPages.PageReference report = new ApexPages.PageReference('/apex/TestSendReport');
        return report.setRedirect(false);
        }
        
          
    public static void executeRpt() {
        System.debug('CALLING REPORT EXPORTER...');        
        ReportName__c mc = ReportName__c.getValues('ReportName');
        strEmailAddr =  mc.RptEmail__c;
        
        System.debug('ReportName:' +  mc.RptName__c);
        System.debug('EmailAddr:' + mc.RptEmail__c);
        integer a = 1;
        ApexPages.PageReference report = new ApexPages.PageReference( '/' + mc.RptName__c + '?csv=1');
        
        Messaging.EmailFileAttachment attachment = new Messaging.EmailFileAttachment();
        attachment.setFileName('report.csv');
        attachment.setBody(report.getContent());
        attachment.setContentType('text/csv');
        Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
        message.setFileAttachments(new Messaging.EmailFileAttachment[] { attachment } );
        message.setSubject('Report');
        message.setPlainTextBody('The report is attached.');
        message.setToAddresses( new String[] { strEmailAddr } );
        Messaging.sendEmail( new Messaging.SingleEmailMessage[] { message } );        
    }
 
}   

 

Unfortunately, nothing happens, but the logs still show all executed OK.

 

 

 

 

sf_evolutionsf_evolution

 

Well,  after re-thinking the entire process, I got it working perfectly (for my needs).

 

I blogged the solution here:

   http://kevindotcar.wix.com/home/apps/blog/how-to-schedule-a-report-to-send

 

Just in case anyone is intersted.

 

Thanks