You need to sign in to do that
Don't have an account?
Dchris222
PDF generation failed. Check the page markup is valid.
I have a VF page that is being populated via a standard controller and a extension. It works just fine in the sandbox, but in production I am recieving the following error: " PDF generation failed. Check the page markup is valid. "
Any input on why this is happing would be appreciated:
edit: I have determined it has to do with the public case comments rendered. It works if I just have the comment body rendered as public, but if I add the created date as well then the error arises.
Page:
<apex:page renderas="pdf" standardController="Case" extensions="PDFServiceExtension"> <apex:stylesheet value="{!$Resource.PDFHeaderFooter}"/> <center> <apex:image url="{!$Resource.MIRLetterhead}" width="700" height="97" /> </center> <apex:panelGrid columns="2" id="theGrid"> <apex:outputLabel value="Case #: " for="Case#" style="font-weight: bold"/> <apex:outputField value="{!Case.CaseNumber}" id="CaNumber"/> <apex:outputLabel value="Date & Time Opened: " for="CaseOpen" style="font-weight: bold"/> <apex:outputField value="{!Case.CreatedDate}" id="CaseOpen"/> <apex:outputLabel value="Date & Time Closed: " for="CaseClosed" style="font-weight: bold"/> <apex:outputField value="{!Case.ClosedDate}" id="CaseClosed"/> <apex:outputLabel value="Status:" for="CaseStatus: " style="font-weight: bold"/> <apex:outputField value="{!Case.Status}" id="CaseStatus"/> <apex:outputLabel value="Type:" for="CaseType: " style="font-weight: bold"/> <apex:outputField value="{!Case.Type}" id="CaseType"/> <apex:outputLabel value="Account: " for="Name" style="font-weight: bold"/> <apex:outputField value="{!Case.Account.name}" id="Name"/> <apex:outputLabel value="Subject: " for="Case#" style="font-weight: bold"/> <apex:outputField value="{!Case.Subject}" id="CaSubj"/> <apex:outputLabel value="Description: " for="Case#" style="font-weight: bold"/> <apex:outputField value="{!Case.Description}" id="CaDesc"/> </apex:panelGrid> <br></br> <apex:outputLabel value="Service Activities:" for="Name" style="font-weight: bold"/> <apex:dataTable value="{!SA}" var="LIs" width="50%" border="1px" > <apex:column headerValue="Service Engineer" value="{!LIs.Contact__c}" headerClass="tableHead"/> <apex:column headerValue="Total Hours" value="{!LIs.Total_Hours__c}"/> <apex:column headerValue="Date Performed" value="{!LIs.Date_Performed__c}"/> </apex:dataTable> <br></br> <apex:outputLabel value="Case Comments:" for="Name2" style="font-weight: bold"/> <apex:pageBlock > <apex:pageBlockTable value="{!case.casecomments}" var="c" width="50%" border="1px" > <apex:column value="{!c.commentbody}" rendered="{!c.isPublished = true}"/> <apex:column value="{!c.createddate}" rendered="{!c.isPublished = true}"/> </apex:pageBlockTable> </apex:pageBlock> </apex:page>
Extension:
public with sharing class PDFServiceExtension { private final Case Ca; public PDFServiceExtension(ApexPages.StandardController CaseController) { this.Ca = (Case)CaseController.getRecord(); } //For Testing Purposes public PDFServiceExtension(Case tcase) { this.Ca = tcase; } // Create a list of type Suite__c and call the query method public List<Service_Activity__c> activityRecords() { return (List<Service_Activity__c>) activityRecords.getRecords(); } // Query the db for the list of Suite__c records to use on the vf page and return a list public ApexPages.StandardSetController activityRecords{ get { if(activityRecords == null) { activityRecords = new ApexPages.StandardSetController(Database.getQueryLocator([Select s.Contact__c, s.Case__c, s.Total_Hours__c, s.Description__c, s.Date_Performed__c from Service_Activity__c s Where s.Case__c =:ApexPages.currentPage().getParameters().get('id')])); } return activityRecords; } set; } public List<Service_Activity__c> getSA() { return (List<Service_Activity__c>) activityRecords.getRecords(); } }
Surprised we haven't run into this before. It looks like whenever you have a dataTable or pageBlockTable that gets rendered, but none of the columns get rendered based on your criteria (essentially, an empty table), it generates some HTML that the PDF renderer does not like. At least, that's what I'm experiencing (not sure the problem is really with createdDate, I can reproduce it with the comment body as well, as long as I have no published case comments on that particular case).
I'll log a bug internally but you should be able to workaround it by putting a rendered attribute on your pageBlockTable (or maybe even your pageBlock? Depends on what you want the UI to look like) that will only display the table if your case has published comments.
So add this to your pageBlock or pageBlockTable: rendered="{!publishedComments > 0}"
And something like this in your extension constructor (with a getter for your publishedComments integer):
publishedComments = [select count() from CaseComment where parentid = :Ca.id and isPublished = true];
Sorry about the workaround but hopefully it will unblock you.
@jwetzler I have seen this before but not in the data table directly - when using apex:repeat to generate a table. Most browsers will accept a blank table, or blank TRs or missing TD's but adobe / pdf will not.
In my experience, the best thing to do when you get the generic PDF generation failed error is to render the page into HTML and then run the HTML thru a parser / validator to locate the error(s) and fix them.
You simply must have valid (to the PDF engine anyway) HTML to generate. Leaving a tag open can cause a failure depending on the tag.
Yeah. In this case all the tags are balanced. I think the problem is the <colgroup> tag that gets generated, but the table has no columns. The PDF renderer gets a little finicky with table structure.
JWetzler,
I added the following to my extension, but I am still recieving the same error message:
The particular case has two public comments and 1 private and the order in which they are public or private seems to determine if it fails or not.
Extension:
Page:
Bummer. Okay then it must be a more general problem with columns. I'll see if I can put more detail in the bug but you should be able to get around it by querying for only published CaseComments and then using the dataTable with that list, rendering your pageblock only if the list isn't empty. Let me know if that works for you.
And yeah it seems that if the very last comment is not public it fails. If the first or second are public it works.
But not having unpublished comments in the collection in the first place should work for you.
Ok, so I created another extension and then tied the data table to it, but I am now geting this error: "List controllers are not supported for CaseComment".
One problem to another, any guidence on this?
Much appreciated
Extension2
Page:
That all seems like overkill. Why are you trying to instantiate a StandardSetController? You shouldn't even need another extension. Just
And then in your page:
I didn't actually save this myself so it's possible I have some compilation errors in there, but that's the general idea.