Use Case
Piece of code that allows PDF to be generated in Batch classes
through a REST webservice. SFDC currently does not allow usage of the
getContent function to generate a PDF from a Visualforce page in a Batch
context. The utility can generate either the Blob representation of the
Visualforce PDF page or insert it as an Attachment to a given record and return
the Attachment salesforce ID.
Solution
Created a REST webservice
utility that can be called from a Batch class which returns the BLOB
representation or an attachment ID from the Visualforce template provided.
Reusable Code
1 Utility Class
public class LetterPrintUtilities {
private static final String STR_HTTP_METHOD_GET = 'GET';
private static final String STR_HTTP_METHOD_POST = 'POST';
private static final String STR_AUTHORIZATION = 'Authorization';
private static final String STR_ACCEPT = 'Accept';
private static final String STR_ACCEPT_VALUE = 'application/json';
private static final String STR_CONTENT_TYPE = 'Content-Type';
private static final String STR_CONTENT_TYPE_VALUE = 'application/json; charset=UTF-8';
private static final String STR_OAUTH = 'OAuth';
private static final String STR_TEST_PDF = 'This is a test BLOB Creation';
private static Http http = new Http();
private static HttpRequest req = new HttpRequest();
private static HttpResponse res;
private Blob pdfContent;
private Id attachmentRec;
private static final Map<String, PageReference> TEMPLATE_NAME_MAPPING = new Map<String, PageReference> {
/** START: DO NOT REMOVE THIS ITEM, THIS IS USED FOR TEST CLASS **/
'test_data_for_test_class' => new PageReference('/apex/test_data_for_test_class'),
/** END **/
'sample_renderaspdf' => Page.SAMPLE_RenderAsPdf
//All keys in this map should be in lower case
};
public Blob getPdfContentBlob() {
return this.pdfContent;
}
public Id getAttachmentId() {
return this.attachmentRec;
}
public void retrieveLetter(PageReference vfPage, Map<String, Object> params) {
this.pdfContent = null;
PageReference pgToGet = vfPage;
if(params != null) {
for(String s : params.keySet()) {
pgToGet.getParameters().put(s, String.valueOf(params.get(s)));
}
}
if(!Test.isRunningTest()) {
this.pdfContent = pgToget.getContentAsPDF();
} else {
this.pdfContent = Blob.toPDF(STR_TEST_PDF);
}
}
public void retrieveLetter(PageReference vfPage, Map<String, Object> params, Id attachTo, String fileName) {
retrieveLetter(vfPage, params);
attachToRecord(attachTo, fileName);
}
public Id attachToRecord(Id recordToAttachTo, String fileName) {
Database.SaveResult result;
if(pdfContent != null) {
Attachment attachment = new Attachment();
attachment.Body = pdfContent;
attachment.Name = fileName + '.pdf';
attachment.ParentId = recordToAttachTo;
try {
result = Database.insert(attachment);
this.attachmentRec = result.getId();
} catch(DmlException dme) {
throw new LetterPrintingException('BATCH_LETTER_EXCEPTION: Attachment insert failed (' + dme.getMessage() + ')');
}
} else {
throw new LetterPrintingException('BATCH_LETTER_EXCEPTION: PDF is not generated');
}
return result.getId();
}
public static Boolean isTemplateAvailable(String templateName) {
return TEMPLATE_NAME_MAPPING.containsKey(templateName);
}
public static PageReference getTemplate(String templateName) {
return TEMPLATE_NAME_MAPPING.get(templateName);
}
private static void setupHttp() {
String authorizationHeader = STR_OAUTH + ' ' + UserInfo.getSessionId();
req.setMethod(STR_HTTP_METHOD_POST);
req.setHeader(STR_AUTHORIZATION, authorizationHeader);
req.setHeader(STR_ACCEPT, STR_ACCEPT_VALUE);
req.setHeader(STR_CONTENT_TYPE, STR_CONTENT_TYPE_VALUE);
}
//base method to be called out
public static Blob generateLetter(PageReference pg, Map<String, String> params) {
setupHttp();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm() + '/services/apexrest/LetterPrintGetBlob/');
String pageUrl = getTemplateFromPageRef(pg);
if(isTemplateAvailable(pageUrl)) {
req.setBody(new LetterRequestPost(pageUrl, params).getJsonValue());
if(!Test.isRunningTest()) {
res = http.send(req);
} else {
res = new HttpResponse();
res.setBody(String.valueOf(Blob.toPDF(STR_TEST_PDF)));
}
}
return Blob.valueOf(res.getBody());
}
public static Blob generateLetter(PageReference pg, Map<String, String> params, Id attachTo, String flName) {
setupHttp();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm() + '/services/apexrest/LetterPrintGetAttachment/');
String pageUrl = getTemplateFromPageRef(pg);
if(isTemplateAvailable(pageUrl)) {
req.setBody(new LetterRequestPostAttachTo(pageUrl, params, attachTo, flName).getJsonValue());
if(!Test.isRunningTest()) {
res = http.send(req);
} else {
res.setBody(String.valueOf(Blob.toPDF(STR_TEST_PDF)));
}
}
return Blob.valueOf(res.getBody());
}
//Class being serialized as JSON to be sent to the REST webservice
private class LetterRequestPost {
String templateName;
Map<String, String> params;
LetterRequestPost(String templateName, Map<String, String> params) {
this.templateName = templateName;
this.params = params;
}
String getJsonValue() {
String jsonVal = JSON.serializePretty(this);
return jsonVal;
}
}
private class LetterRequestPostAttachTo {
String templateName;
Map<String, String> params;
String fileName;
Id recordToAttachTo;
LetterRequestPostAttachTo(String templateName, Map<String, String> params, Id attachTo, String flName) {
this.templateName = templateName;
this.params = params;
this.recordToAttachTo = attachTo;
this.fileName = flName;
}
String getJsonValue() {
String jsonVal = JSON.serializePretty(this);
return jsonVal;
}
}
private static String getTemplateFromPageRef(PageReference pr){
String baseStr = pr.getURL();
if(baseStr != null) {
while(baseStr.contains('/')) {
baseStr = baseStr.substringAfter('/');
}
if(baseStr.contains('?')) {
baseStr = baseStr.substringAfter('?');
}
}
return baseStr;
}
class LetterPrintingException extends Exception {}
}
private static final String STR_HTTP_METHOD_GET = 'GET';
private static final String STR_HTTP_METHOD_POST = 'POST';
private static final String STR_AUTHORIZATION = 'Authorization';
private static final String STR_ACCEPT = 'Accept';
private static final String STR_ACCEPT_VALUE = 'application/json';
private static final String STR_CONTENT_TYPE = 'Content-Type';
private static final String STR_CONTENT_TYPE_VALUE = 'application/json; charset=UTF-8';
private static final String STR_OAUTH = 'OAuth';
private static final String STR_TEST_PDF = 'This is a test BLOB Creation';
private static Http http = new Http();
private static HttpRequest req = new HttpRequest();
private static HttpResponse res;
private Blob pdfContent;
private Id attachmentRec;
private static final Map<String, PageReference> TEMPLATE_NAME_MAPPING = new Map<String, PageReference> {
/** START: DO NOT REMOVE THIS ITEM, THIS IS USED FOR TEST CLASS **/
'test_data_for_test_class' => new PageReference('/apex/test_data_for_test_class'),
/** END **/
'sample_renderaspdf' => Page.SAMPLE_RenderAsPdf
//All keys in this map should be in lower case
};
public Blob getPdfContentBlob() {
return this.pdfContent;
}
public Id getAttachmentId() {
return this.attachmentRec;
}
public void retrieveLetter(PageReference vfPage, Map<String, Object> params) {
this.pdfContent = null;
PageReference pgToGet = vfPage;
if(params != null) {
for(String s : params.keySet()) {
pgToGet.getParameters().put(s, String.valueOf(params.get(s)));
}
}
if(!Test.isRunningTest()) {
this.pdfContent = pgToget.getContentAsPDF();
} else {
this.pdfContent = Blob.toPDF(STR_TEST_PDF);
}
}
public void retrieveLetter(PageReference vfPage, Map<String, Object> params, Id attachTo, String fileName) {
retrieveLetter(vfPage, params);
attachToRecord(attachTo, fileName);
}
public Id attachToRecord(Id recordToAttachTo, String fileName) {
Database.SaveResult result;
if(pdfContent != null) {
Attachment attachment = new Attachment();
attachment.Body = pdfContent;
attachment.Name = fileName + '.pdf';
attachment.ParentId = recordToAttachTo;
try {
result = Database.insert(attachment);
this.attachmentRec = result.getId();
} catch(DmlException dme) {
throw new LetterPrintingException('BATCH_LETTER_EXCEPTION: Attachment insert failed (' + dme.getMessage() + ')');
}
} else {
throw new LetterPrintingException('BATCH_LETTER_EXCEPTION: PDF is not generated');
}
return result.getId();
}
public static Boolean isTemplateAvailable(String templateName) {
return TEMPLATE_NAME_MAPPING.containsKey(templateName);
}
public static PageReference getTemplate(String templateName) {
return TEMPLATE_NAME_MAPPING.get(templateName);
}
private static void setupHttp() {
String authorizationHeader = STR_OAUTH + ' ' + UserInfo.getSessionId();
req.setMethod(STR_HTTP_METHOD_POST);
req.setHeader(STR_AUTHORIZATION, authorizationHeader);
req.setHeader(STR_ACCEPT, STR_ACCEPT_VALUE);
req.setHeader(STR_CONTENT_TYPE, STR_CONTENT_TYPE_VALUE);
}
//base method to be called out
public static Blob generateLetter(PageReference pg, Map<String, String> params) {
setupHttp();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm() + '/services/apexrest/LetterPrintGetBlob/');
String pageUrl = getTemplateFromPageRef(pg);
if(isTemplateAvailable(pageUrl)) {
req.setBody(new LetterRequestPost(pageUrl, params).getJsonValue());
if(!Test.isRunningTest()) {
res = http.send(req);
} else {
res = new HttpResponse();
res.setBody(String.valueOf(Blob.toPDF(STR_TEST_PDF)));
}
}
return Blob.valueOf(res.getBody());
}
public static Blob generateLetter(PageReference pg, Map<String, String> params, Id attachTo, String flName) {
setupHttp();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm() + '/services/apexrest/LetterPrintGetAttachment/');
String pageUrl = getTemplateFromPageRef(pg);
if(isTemplateAvailable(pageUrl)) {
req.setBody(new LetterRequestPostAttachTo(pageUrl, params, attachTo, flName).getJsonValue());
if(!Test.isRunningTest()) {
res = http.send(req);
} else {
res.setBody(String.valueOf(Blob.toPDF(STR_TEST_PDF)));
}
}
return Blob.valueOf(res.getBody());
}
//Class being serialized as JSON to be sent to the REST webservice
private class LetterRequestPost {
String templateName;
Map<String, String> params;
LetterRequestPost(String templateName, Map<String, String> params) {
this.templateName = templateName;
this.params = params;
}
String getJsonValue() {
String jsonVal = JSON.serializePretty(this);
return jsonVal;
}
}
private class LetterRequestPostAttachTo {
String templateName;
Map<String, String> params;
String fileName;
Id recordToAttachTo;
LetterRequestPostAttachTo(String templateName, Map<String, String> params, Id attachTo, String flName) {
this.templateName = templateName;
this.params = params;
this.recordToAttachTo = attachTo;
this.fileName = flName;
}
String getJsonValue() {
String jsonVal = JSON.serializePretty(this);
return jsonVal;
}
}
private static String getTemplateFromPageRef(PageReference pr){
String baseStr = pr.getURL();
if(baseStr != null) {
while(baseStr.contains('/')) {
baseStr = baseStr.substringAfter('/');
}
if(baseStr.contains('?')) {
baseStr = baseStr.substringAfter('?');
}
}
return baseStr;
}
class LetterPrintingException extends Exception {}
}
2)
Web service classes
@RestResource(urlMapping='/LetterPrintGetAttachment/*')
global class LetterPrintingAttachment {
/**
*
* HTTP Post service that returns the Id of the inserted
* Attachment from the generated pdf
*
**/
@HttpPost
global static String generateLetterAttachment(String templateName, Map<String, String> params, Id recordToAttachTo, String fileName) {
LetterPrintUtilities util = new LetterPrintUtilities();
if(LetterPrintUtilities.isTemplateAvailable(templateName)) {
util.retrieveLetter(
LetterPrintUtilities.getTemplate(templateName),
params,
recordToAttachTo,
fileName
);
}
return util.getAttachmentId();
}
}
global class LetterPrintingAttachment {
/**
*
* HTTP Post service that returns the Id of the inserted
* Attachment from the generated pdf
*
**/
@HttpPost
global static String generateLetterAttachment(String templateName, Map<String, String> params, Id recordToAttachTo, String fileName) {
LetterPrintUtilities util = new LetterPrintUtilities();
if(LetterPrintUtilities.isTemplateAvailable(templateName)) {
util.retrieveLetter(
LetterPrintUtilities.getTemplate(templateName),
params,
recordToAttachTo,
fileName
);
}
return util.getAttachmentId();
}
}
@RestResource(urlMapping='/LetterPrintGetBlob/*')
global class LetterPrintingBlob {
/**
*
* HTTP Post service that returns the Blob representation
* of the PDF VF Page which is deserialized in the Util
* class
*
**/
@HttpPost
global static String generateLetterBlob(String templateName, Map<String, String> params) {
LetterPrintUtilities util = new LetterPrintUtilities();
if(LetterPrintUtilities.isTemplateAvailable(templateName)) {
util.retrieveLetter(
LetterPrintUtilities.getTemplate(templateName),
params
);
}
return EncodingUtil.base64Encode(util.getPdfContentBlob());
}
}
global class LetterPrintingBlob {
/**
*
* HTTP Post service that returns the Blob representation
* of the PDF VF Page which is deserialized in the Util
* class
*
**/
@HttpPost
global static String generateLetterBlob(String templateName, Map<String, String> params) {
LetterPrintUtilities util = new LetterPrintUtilities();
if(LetterPrintUtilities.isTemplateAvailable(templateName)) {
util.retrieveLetter(
LetterPrintUtilities.getTemplate(templateName),
params
);
}
return EncodingUtil.base64Encode(util.getPdfContentBlob());
}
}
Example:
Below is an
example how the Above code can be used.
Batch Class:
Blob blobGenerated =
LetterPrintUtilities.generateLetter(
Page.ExistingVfPage,
//an existing VF page to be used as template
new
Map<String, String> { ‘Id’ => ‘00100000000AJHS’} //url
parameters to be passed to the VF template
);
Id attachmentId =
LetterPrintUtilities.generateLetter(
Page.ExistingVfPage,
//an existing VF page to be used as template
new Map<String, String> {
‘Id’ => ‘00100000000AJHS’}, //url parameters to be passed to the VF template
‘00100000000AJHS’’,
//if an attachment is to be generated, the attachment will be attached to this
record
‘PDF Order form’
//the attachment’s file name
);
The method returns the BLOB content of the generated PDF or the ID of the attachment generated.
No comments:
Post a Comment