My Question is exactly same as this one - https://developer.salesforce.com/forums/?id=9060G0000005MLWQA2
But i will give more details.
We just turned on Lightning Knowledge on in our environment, and goal is to write a script that can update recordtype on all Draft and published articles.
For published articles, i need to do this -
Step 1 - Make a rest call to create a draft version
Step 2 - Make a rest call to update draft version (change its recordtype)
Step 3 - Make a rest call to publish the above draft version
For Articles that are in draft, i can reuse the code for Step 2 (even though updating draft can be done by simple database changes via apex, but that causes issue in conjunction with Step 3 if everything is done in one transaction .. so i am sticking to rest call for step 2).
Since there are over 4000 articles, and each could require upto 3 rest calls, i am writing a batch apex, and intend to run it with a batch size of 1.
For reference, i am using this to make rest calls - https://www.jitendrazaa.com/blog/salesforce/call-salesforce-rest-api-from-apex/
I wrote code for step 2, and tried testing it, but getting the error {"errorCode" : "INVALID_SESSION_ID", "message" : "Session expired or invalid"}
Instead of batch class, if i call my utility method directly from workbench or anonymous window, it works (for a single article).
here are my codes
batch class
global class pf_knowledgeMigrator implements Database.Batchable<sObject>, Database.AllowsCallouts{
global Database.QueryLocator start(Database.BatchableContext BC){
String query = 'Select Id, PublishStatus from Knowledge__kav where PublishStatus=\'Draft\' and IsLatestVersion= True and RecordTypeId=null';
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<Knowledge__kav> articles){
for(Knowledge__kav currentArticle : articles){
knowledgeMigratorHelper.processDraftArticle(currentArticle);
}
}
global void finish(Database.BatchableContext BC) {
}
}
My helper class
public without sharing class knowledgeMigratorHelper{
private static Id howToRecTypeId = [Select Id from RecordType where DeveloperName = 'How_To' limit 1].Id;
public static void processDraftArticle(Knowledge__kav article){
String articleId = String.ValueOf(article.Id);
String howToRecordTypeIdString = String.ValueOf(howToRecTypeId);
HttpResponse httpResponse = changeRecordType(articleId,howToRecordTypeIdString);
if(httpResponse.getStatusCode() != 204){
String response = JSON.serializePretty( JSON.deserializeUntyped(httpResponse.getBody()) );
System.debug(response);
}
}
/*
* Utility Method to change recordType of a draft version of an article
*/
public static HttpResponse changeRecordType(String articleId, String recTypeId){
String sfdcURL = URL.getSalesforceBaseUrl().toExternalForm();
String restAPIURL = sfdcURL + '/services/data/v40.0/sobjects/Knowledge__kav/'+articleId+'?_HttpMethod=PATCH';
HttpRequest httpRequest = new HttpRequest();
httpRequest.setMethod('POST');
httpRequest.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionId());
httpRequest.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
httpRequest.setHeader('Content-Type', 'application/json');
httpRequest.setEndpoint(restAPIURL);
httpRequest.setBody('{ "RecordTypeId": "' + recTypeId + '"}');
Http http = new Http();
HttpResponse httpResponse = http.send(httpRequest);
return httpResponse;
}
}
When i run the command Database.executeBatch(new pf_knowledgeMigrator(),1), i get that error
However, if i directly use console anonymous window or workbench and test my utility method like following, it works -
String articleId = 'ka1c00000000YYvAAM';
String recTypeId = '012c0000000AWxvAAG';
HttpResponse httpResponse = knowledgeMigratorHelper.changeRecordType(articleId,recTypeId);
System.debug('@@@@ response code'+httpResponse.getStatusCode());
Doing above will udpate the recordtype of article with Id ka1c00000000YYvAAM
So something is different when REST callout is made via batch. Not sure how i can make this work