Question
Is it possible to create or update a NamedCredential
from within Apex
?
Investigation
I looked into available options, and it seems the SOAP API
only supports the describeSObjects()
, query()
, and retrieve()
operations. The Tooling API
doesn't seem to support the object at all. But the Metadata API
does!
Let's play around with some scripts in Execute Anonymous
and see what we can do with the Apex Wrapper Salesforce Metadata API
.
Working with the Metadata API
Helper Methods
Here are some bare-bones helper methods pulled out of the MetadataServiceExamples
class:
static MetadataService.MetadataPort createService()
{
MetadataService.MetadataPort service = new MetadataService.MetadataPort();
service.SessionHeader = new MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = UserInfo.getSessionId();
return service;
}
static List<MetadataService.SaveResult> createMetadata(MetadataService.Metadata input)
{
return createService().createMetadata(new List<MetadataService.Metadata> { input });
}
static List<MetadataService.SaveResult> updateMetadata(MetadataService.Metadata input)
{
return createService().updateMetadata(new List<MetadataService.Metadata> { input });
}
static List<MetadataService.DeleteResult> deleteMetadata(String type, String fullName)
{
return createService().deleteMetadata(type, new List<String> { fullName });
}
NamedCredential
I tried to run a NamedCredential
through these methods and was not able to get createMetadata
or updateMetadata
to work. The errors are included below. To my surprise, however, deleteMetadata
runs successfully if the other methods are left out. I don't see any mention in the documentation of which operations are supported...
Script
MetadataService.NamedCredential credential = new MetadataService.NamedCredential();
credential.fullName = 'Demo_Credential';
credential.label = 'Demo Credential';
credential.endpoint = 'https://www.DEMO2.com';
system.debug(createMetadata(credential));
system.debug(updateMetadata(credential));
system.debug(deleteMetadata('NamedCredential', credential.fullName));
Error on createMetadata
Line: 11534, Column: 1
System.CalloutException: Web service callout failed: WebService returned a SOAP Fault: '' is not a valid value for the enum 'ExternalPrincipalType' faultcode=soapenv:Client faultactor=
Error on updateMetadata
Line: 11364, Column: 1
System.CalloutException: Web service callout failed: WebService returned a SOAP Fault: '' is not a valid value for the enum 'ExternalPrincipalType' faultcode=soapenv:Client faultactor=
ApexPage
Just to make sure my installation works correctly, I slightly tweaked some examples from the MetadataServiceExamples
class. The createMetadata()
, updateMetadata()
, and deleteMetadata()
calls each work fine for the ApexPage
type.
Script
MetadataService.ApexPage apexPage = new MetadataService.ApexPage();
apexPage.apiVersion = 25;
apexPage.fullName = 'test';
apexPage.label = 'Test Page';
apexPage.content = EncodingUtil.base64Encode(Blob.valueOf('<apex:page/>'));
system.debug(createMetadata(apexPage));
system.debug(updateMetadata(apexPage));
system.debug(deleteMetadata('ApexPage', apexPage.fullName));
Abbreviated Logs
(SaveResult:[errors=null, fullName=test, success=true])
(SaveResult:[errors=null, fullName=test, success=true])
(DeleteResult:[errors=null, fullName=test, success=true])