Compared to past updates the Summer’14 update to the Salesforce Metadata API might not look that exciting at first glance, i know it took me a second look to get more excited! This time its perhaps whats not in it thats the most interesting and what it means for new developers trying to use this often elusive API for the first time!
Basically Salesforce have removed from API 31 onwards most of the pesky async operations. For those who read my past blog on these operations, you’ll see that they require a fair bit of work on the callers behalf to keep polling Salesforce for the results. Spring’14 introduced immediate versions of these operations alongside the old async ones, now with Summer’14 the old ones have gone completely from the WSDL! Before you panic, fear not, if your using the API 30 or below endpoints in existing solutions they are still present.
It is clear now that the Salesforce developers behind the Metadata API have been on a mission to clean it up, simplify it and make it more in alignment with how you currently use the Partner API, REST and Tooling API’s from realtime CRUD API perspective. It now also sports an upsert operation, meaning that the set of database operations you can now perform on the vast array of Metadata Component types it contains is complete! As a result it is now much easier to see what operations you need to get things done and because they are immediate your calling code is now much much simpler!
Salesforce is quite special in having an additional database operation in its terminology, known as upsert. Its is available in Apex and through its existing API’s, and now in the Metadata API. For those not familiar, it basically short cuts the need to check if a record or in this case a component already exists if your aim is to create it if it doesn’t exist or update it if it does.
MetadataService.MetadataPort service = createService(); MetadataService.CustomObject customObject = new MetadataService.CustomObject(); customObject.fullName = 'Test__c'; customObject.label = 'Test'; customObject.pluralLabel = 'Tests Upsert'; customObject.nameField = new MetadataService.CustomField(); customObject.nameField.type_x = 'Text'; customObject.nameField.label = 'Test Record Upsert'; customObject.deploymentStatus = 'Deployed'; customObject.sharingModel = 'ReadWrite'; List<MetadataService.UpsertResult> results = service.upsertMetadata( new MetadataService.Metadata[] { customObject });
In addition to these methods some of the old ones still exist, indeed there is no escaping the fact that if your wanting to create or retrieve many metadata components at once the retrieve and and deploy operations are still needed, and understandably still require aysnc type handling by the caller, since they could be quite long running operations.
Upgrade Advice: As always, i’ve updated the Apex Metadata API library to reflect the very latest release of the Metadata API. So if you are upgrading to the latest MetadataService.cls be aware the older methods will also not be present. The release notes here also cover other changes and new features. If your worried about this and don’t need any new component types for an existing project my advice is to stay with the earlier one and reserve this new version for new work. Finally i’ve retired some of the samples from the Apex Metadata API library focusing on using the Async API’s in batch and in Visualforce, as these would not compile anyway, they are of course still accessible through the repos history.
Of course, with most things there is always room for improvement! The ability to be able to run SOQL queries over the Metadata objects would be most welcome, the listMetadata method is just not flexible enough. Also the ability to create Apex Class and Apex Triggers without having to resort to using the deploy operation would also be appreciated.
I think Salesforce have done an amazing job at being committed to their API true to the core strategy here and with these changes it makes it so easy to go forth and do some cool stuff with the API without the extra overhead it had previously. No excuses now! ;-)
