2
votes

I need to generate automatically multiple PDF files and save them as attachments in its correspondent objects records. I have tried to resolve this topic making use of a batch file and a rendered visualForce page as 'PDF' but Salesforce have here a limit not allowing to use a getContent() method in a batch class.

Searching in the internet I have found this possible solution:

Why are HTML emails being sent by a APEX Schedulable class being delivered with blank bodies?

It propose to:

  1. Create a class which implements the Schedulable interface.
  2. Have an execute() method call and a @future method.
  3. Create a @future method that call a web service enabled method in the class that sends the email.

The problem I found is when I try to authenticate in my Web Services (REST) inside Salesforce (http://help.salesforce.com/help/doc/en/remoteaccess_oauth_web_server_flow.htm)

In the first step I am making a request and I get a code through the callback URL, but It is impossible to know how to read this parameter from Salesforce. In the answer I don't have a method called 'getParameter()' and the body is empty.

As an example:

Request: https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id= 3MVG9lKcPoNINVBIPJjdw1J9LLM82HnFVVX19KY1uA5mu0QqEWhqKpoW3svG3XHrXDiCQjK1mdgAvhCscA 9GE&redirect_uri=https%3A%2F%2Fwww.mysite.com%2Fcode_callback.jsp&state=mystate

Response: https://www.mysite.com/code_callback.jsp?code=aPrxsmIEeqM9&state=mystate

It exists any way to connect with my Webservices making the call inside Salesforce in order to implement this solution??

It would be easier if a make a call from an external application but inside salesforce???

Can you suggest any possible solution???

2

2 Answers

1
votes

(Necromancy of old questions ;))

How about this:

  1. Directly from your context or from Schedulable class...
  2. Call @future up to 10 times
  3. Each @future can send up to 10 callouts, use them to RESTfully access your VF page with renderAs="pdf" and save the content as your attachment?
  4. If 100 attachments aren't enough - play with daisy-chaining of batches. I believe since Summer or Winter '13 finish() method in a batch can be used to fire Database.execute() on next batch ;)

As to how exactly get REST access to the PDF - you can use either my question https://salesforce.stackexchange.com/questions/4692/screen-scrape-salesforce-with-rest-get-call-from-apex or maybe my end solution for saving reports: https://salesforce.stackexchange.com/questions/4303/scheduled-reports-as-attachment (you'll need only the authentication part I imagine + of course a working entry in remote site settings).

This is under assumption that sid cookie will work on VF pages as good as it does on standard ones... Good luck?

0
votes

Since Winter '16 release, PageReference.getContent can be called from Batch Apex.

Spread the PDF attachment generation across multiple batch execution contexts depending on the size and count you need to generate - getContent is an HTTP request and the servlet can take a long time to respond.

https://releasenotes.docs.salesforce.com/en-us/winter16/release-notes/rn_apex_pagereference_getcontent.htm#rn_apex_pagereference_getcontent

You can now make calls to the getContent() and getContentAsPdf() methods of the PageReference class from within asynchronous Apex such as Batch Apex, Schedulable and Queueable classes, and @future methods. This allows you to design much more flexible and scalable services that, for example, render Visualforce pages as PDF files.

For the purposes of limits and restrictions, calls to getContent() (and getContentAsPdf(), which behaves the same) are treated as callouts. The behavior and restrictions vary depending on the PageReference it’s called on, and in certain cases are relaxed. There are three different possibilities.

PageReference instances that explicitly reference a Visualforce page For example, Page.existingPageName. Calls to getContent() aren’t subject to either the maximum concurrent callouts limit or the maximum total callouts per transaction limit.

Additionally, only PageReference instances that reference a Visualforce page can call getContent() from scheduled Apex, that is, Apex classes that implement the Schedulable interface.

PageReference instances that reference a Salesforce URL:

For example, PageReference('/' + recordId). Calls to getContent() for Salesforce URLs aren’t subject to the maximum concurrent callouts limit, but they are subject to the maximum total callouts per transaction limit.

PageReference instances that reference an external URL:

For example, PageReference('https://www.google.com/'). Calls to getContent() for external URLs are subject to both the maximum concurrent callouts limit and the maximum total callouts per transaction limit.

Even when calls to getContent() and getContentAsPdf() aren’t tracked against callout limits, they’re still subject to the usual Apex limits such as CPU time, etc. These limits are cumulative across all callouts within the originating transaction.

Finally, we’ve relaxed the restrictions on calling getContent() and getContentAsPdf() after performing DML operations (excluding creating Savepoints). If the calls to getContent() and getContentAsPdf() are internal calls, they’re now allowed. External callouts after DML operations are still blocked, and you still can’t make callouts from within getContent() calls themselves, that is, during the rendering of the page.