I have a community site with some partner users on it, and there's a specific record that I want to make available to render as PDF and be saved as attachment on the same record.

Rendering the PDF using Apex getContentAsPDF() is the issue here. When the link to the page is accessed through the browser, the PDF is displayed correctly. However, when accessing the exact same URL from within apex, the PDF is still rendered, but almost all of the tags using apex:outputText are blank, leaving the whole document incomplete.

There is one specific variable on my document that is generated by processing some related records, and this one field shows up on the document. The other fields are references to the record and child records (master-detail relationship).

While reading the log when accessing the page, I can't see the page constructor being called, but the field I mentioned earlier is calculated when the constructor is called (I've placed System.debugs on the constructor to check this).

It is worth noting that the community isn't public. Users need to be authenticated to access it. So I don't think the Site's Public Settings have got something to do in this case.

Some conclusions:

  • It is not a page access issue, since the page can be accessed anyway. The content is the problem.
  • It is not a class access issue, for the same reason as above.
  • It is not related to the variables, since the PDF is perfectly rendered outside Apex and inside the community.

Pseudo code being used:

On the page's controller:

public without sharing class MyCustomController {
    public MyCustomObject__c record {get;set;}
    public MyCustomObject[] children {get;set;}
    public String calculatedField {get;set;}

    public MyCustomController (ApexPages.StandardController stdc) {
        this.record = MyCustomRecordSelector.getById(stdc.getId());
        this.children = MyCustomRecordChildSelector.getByInvoice(stdc.getId());
        this.calculatedField = this.doSomeProcessing(this.children);

    public String doSomeProcessing (List<MyCustomObject> child_records) {
        return SomeStaticClass.doSomeProcessing(child_records);

The class that is called by the button:

// page's name (page_name) is passed along with
// the record's Id and the page's name

Blob pdf;
if (page_name.toLowerCase() == 'PageA') {
    pdf = getPageA(MyCustomRecord.Id);
} else if (page_name.toLowerCase() == 'PageB') {
    pdf = getPageB(MyCustomRecord.Id);
} else if (page_name.toLowerCase() == 'PageC') {
    pdf = getPageC(MyCustomRecord.Id);

Attachment att = new Attachment(
    ParentId = MyCustomRecord.Id,
    Body = Test.isRunningTest() ? Blob.valueOf('test') : pdf,
    Name = 'Attachment.pdf',
    ContentType = 'application/pdf',
insert att;

// code calls this method, which accesses the
// page and retrieves its content as PDF

private static Blob getPageB (Id record_id) {
    PageReference ref = Page.PageB;
    ref.getParameters().put('Id', record_id);
    return Test.isRunningTest() ? Blob.valueOf('test') : ref.getContentAsPDF();
  • FYI == performs case-insensitive comparison. – Adrian Larson May 30 '17 at 17:13
  • Even though 'pagea' == 'PageA' is true, the pages have absolutely different names... But that was interesting to know! – Renato Oliveira May 30 '17 at 17:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.