4

I have a business requirement to attach a pdf document (visualforce rendered as pdf) to Notes and Attachments on a record when that record gets updated. Since we can't use getContentAsPDF() in the context of a trigger, I am attempting to create a Web Service that will run asyncronously to perform this task. Thanks go to jungleeforce for this post (http://jungleeforce.wordpress.com/2014/06/11/generate-a-pdf-and-attach-it-to-record-from-a-trigger-in-salesforce-restful/). With some minor customization tweaks I got this working for a single record update. However when I perform a bulk load, I am getting the following errror from the FutureHandler Operation (as seen in the Debug Log). I am calling out from the same org that I am calling into.

10:02:35.245 (245356383)|CALLOUT_RESPONSE|[48]|System.HttpResponse[Status=Unauthorized, StatusCode=401]

I know why I am getting this, but I don't know how to resolve. I am getting this issue because I am passing userInfo.getSessionId() to the asyncronous @future method. Since asyncronous processes don't run in a user context I am not getting a

session id....hence Status=Unauthorized.

I have tried creating a connected app and using the Consumer Key and Consumer Secret. I'm not certain if this the correct approach and if so I need to know how to correctly use this Key and Secret.

Here is the trigger and two classes that I'm using to perform this task.

Please advise on how I can get my access code for this asyncronous process.

Thank you very much.

Trigger

trigger pdfAttachTrigger on DealerPlanning__c (after update)
{
list<id>dealerPlanIdList = new list<id>();
map<id,id> dealerPlanAcctMap = new map<id,id>();

for(DealerPlanning__c dealPlan: trigger.new)
{
  dealerPlanIdList.add(dealPlan.id);
  dealerPlanAcctMap.put(dealPlan.id,dealPlan.account__c);
}

DealerPlanTriggerController.addPDFAttach(userInfo.getSessionId(), dealerPlanIdList, dealerPlanAcctMap);
}

Class with @Future Method

global class DealerPlanTriggerController
{
    @Future(callout=true)
    public static void addPDFAttach(string sessionId, list<id> dealerPlanIdList, map<id,id> dealerPlanAcctMap)
    {
       HttpRequest req = new HttpRequest();
       req.setEndpoint('https://'+URL.getSalesforceBaseUrl().getHost()+'/services/apexrest/addPDFtoRecord/');
       req.setMethod('POST');
       req.setBody('{"dealerPlanAcctMap":'+JSON.serialize(dealerPlanAcctMap)+',"dealerPlanIdList":'+JSON.serialize(dealerPlanIdList)+'}');
       req.setHeader('Authorization', 'Bearer '+ sessionId);
       req.setHeader('Content-Type', 'application/json');
       Http http = new Http();

       if(!test.isRunningTest())
       {
           HTTPResponse res = http.send(req);
       }
    }
}

Class with @RestResource

@RestResource(urlMapping='/addPDFtoRecord/*')
global with sharing class AddPDFtoRecordREST
{  
  @HttpPost
    global static void doPost(map<String,String> dealerPlanAcctMap, list<String> dealerPlanIdList) {

       list<attachment> insertAttachment = new list<attachment>();

        for(String dpId: dealerPlanIdList)
        {
            //create a pageReference instance of the VF page.
            pageReference pdf = Page.PI_Certificate;
            //pass the Account Id parameter to the class.
            pdf.getParameters().put('accountID', dealerPlanAcctMap.get(dpId));

            Attachment attach = new Attachment();
            Blob body;
            if(!test.isRunningTest()){
                body = pdf.getContent();
            }else{
                body=blob.valueOf('TestString');
            }

            attach.Body = body;
            attach.Name = 'pdfName'+dpId+'.pdf';
            attach.IsPrivate = false;
            attach.ParentId = dpId;//This is the record to which the pdf will be attached
            insertAttachment.add(attach);
         }

         //insert the list
         insert insertAttachment;
    }
}
1

Seems like you got your issue right. As for solution to get a session id, go through this SessionID problem in Schedule Batch class

As pointed out in the answers, what you need is to perform login from apex so as to get the Session Id

  • 1
    Thanks A-d for taking the time to post an answer to my question. My scenario is a bit different in that we can not use the renderAs() attribute in a batch context. However I did find a post from Infallible Techie that go me through the Session Id issue using SOAP (infallibletechie.com/2012/04/…). However, now my issue is that I'm experienceing Timeout issues (even after setting the max Timeout at 120000ms) when I try and load a set of more than 200 records at a time. The business needs to update approximately 1200 records. This is not optimal. – JD_06 Sep 17 '14 at 13:55
  • 2
    can you reduce the size of the batch scope from the default (200) to something smaller - like '1' ? – cropredy Jan 26 '15 at 23:51

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.