No, your eyes are not deceiving you! Since the Summer’13 release, you can now automate the installation and uninstall of managed packages! The main use case for this I guess is for those building Continuous Integration build systems using Apache Ant. Where they are deploying code which requires dependent packages to be installed before deployment.
In addition this is also a useful API for building package management tools and UI’s to help administrators install other packages you offer via a kind of package menu! Thus I’ll show how to use it from my Apex Metadata API wrapper.
From Ant via <installPackage> and <uninstallPackage> Tasks
So first lets look at doing this via Ant. You’ll need to download the Force.com Migration Toolkit from your Tools page. I’ve placed the ant-salesforce.jar file in a lib subfolder as per the reference in the sample below.
You can only deploy the new InstalledPackage component type that describes the package to install, on its own. Though it still requires the usual folder structure and package.xml file before using the usual sf:deploy Ant task. To make things easier, I’ve put together a couple of Ant marcos to distill its use a bit further. You can download the ant-salesforce.xml file containing the macro. After that its as easy as this….
<project name="installdemo" default="build" basedir="."> <!-- Load standard properties --> <property file="${basedir}/build.properties"/> <!-- Import macros around sf:deploy to install/uninstall packages --> <import file="${basedir}/lib/ant-salesforce.xml"/> <!-- Default target --> <target name="build"> <!-- Install the package with namespace packagea --> <installPackage namespace="packagea" version="1.0" packagePassword="fred1234" username="${sf.username}" password="${sf.password}"/> <!-- Uninstall the package with namespace pacakgea --> <uninstallPackage namespace="packagea" username="${sf.username}" password="${sf.password}"/> </target> </project>
Note: The packagePassword attribute is optional.
From Apex via Metadata API Apex Wrapper
This is how its done via the Metadata API directly, in Apex (though the following is more or less the same in Java). Note fullName in the samples below is used to pass the namespace of the managed package being referenced.
// Install packageA, then pacakgeB MetadataService.InstalledPackage installedPackageA = new MetadataService.InstalledPackage(); installedPackageA.versionNumber = '1.0'; installedPackageA.password = 'fred1234'; installedPackageA.fullName = 'packagea'; MetadataService.InstalledPackage installedPackageB = new MetadataService.InstalledPackage(); installedPackageB.versionNumber = '1.0'; installedPackageB.fullName = 'packageb'; MetadataService.AsyncResult[] results = createService().create( new List<MetadataService.Metadata> { installedPackageA, installedPackageB });
And to uninstall…
// Uninstall packages MetadataService.InstalledPackage installedPackageA = new MetadataService.InstalledPackage(); installedPackageA.fullName = 'packagea'; MetadataService.InstalledPackage installedPackageB = new MetadataService.InstalledPackage(); installedPackageB.fullName = 'packageb'; MetadataService.AsyncResult[] results = createService().deleteMetadata( new List<MetadataService.Metadata> { installedPackageA, installedPackageB });
As described in the Metadata API for Apex docs you need to handle the AsyncResult’s via VF actionPoller or Batch Apex. For Batch Apex, replace the last line of the install sample with the following to process the installation API calls in batch and have the job email you the results.
MetadataCreateJob.run( new List<MetadataCreateJob.Item> { new MetadataCreateJob.Item(installedPackageA ), new MetadataCreateJob.Item(installedPackageB ) }, new MetadataCreateJob.EmailNotificationMetadataAsyncCallback());
List Packages Installed in an Org
I recently answered this question on StackExchange that gives further information on dynamically listing packages in an org. The answer goes into more details but basically the following Ant tasks provided by Salesforce are quite handy!
<sf:listMetadata username="${sf.username}" password="${sf.password}" metadataType="InstalledPackage"/> <sf:bulkRetrieve username="${sf.username}" password="${sf.password}" metadataType="InstalledPackage" retrieveTarget="${basedir}/installedPackages"/>
Possibilities!
For me the above is a really exciting possibility, you could for example develop a VF page as part of your core package that allows administrators to see other extension packages available with your package and install them directly! Now lets wait to see when the ability to API drive the packaging process arrives, in the meantime enjoy!
June 25, 2013 at 1:10 pm
Reblogged this on Sutoprise Avenue, A SutoCom Source.
Pingback: Managed packages can take hours to become available | Force 201
November 7, 2013 at 2:52 am
miumiu サンダル
April 16, 2014 at 2:48 pm
Hi Andy, great post by the way!
Are you missing the serverurl attribute from your task within ant-salesforce.xml?
April 17, 2014 at 10:57 am
Yes it would appear i am! Do you need a hand in adding this to your copy?
Pingback: Calling Salesforce API’s from Ant Script – Querying Records | Andy in the Cloud
June 10, 2015 at 10:38 am
Hi Andy,
I have implemented a “Managed Package Installer” in Apex for my companies’ Salesforce Application.
It has been working for the last month in our test orgs until yesterday I got an error saying “no clean data columns available for custom fields”.
The package has a lot of custom fields associated with it. When I delete the installed package metadata does it delete all of the custom fields associated with this package as well. I am wondering if this is the cause of the error.
I appreciate any help you can offer me.
Regards,
Ger
June 11, 2015 at 6:58 pm
It should yes, worth trying again in few hours, if not I would ask Salesforce support to take a look.
June 12, 2015 at 7:38 am
Hi Andy,
It turns out when you Delete an Installed package using the CRUD API methods it literally does just that. It does not delete the custom objects/fields etc.
They will be gone from the SF UI and will not be accessible via workbench either but they will still be there in backend somewhere. Apparently it is a Bug on the Salesforce side and when they build up I get the “no clean data columns available for custom fields” error.
I wrote my package installer in APEX using the CRUD API methods.
I will try using the second method listed above (the one that is suggested on the SF Docs for automating managed package installations https://developer.salesforce.com/docs/atlas.en-us.packagingGuide.meta/packagingGuide/packaging_api_introduction.htm )
I will be sure to let you know the outcome as I can test it rigorously in one of my Developer Orgs.
Cheers,
Ger
October 27, 2015 at 8:49 pm
Hi Andy,
Is there a way to automate package upload itself when creating managed package?
Thanks,
Jinesh
October 28, 2015 at 9:04 pm
Sadly not currently, though this will I am sure arrive one day… 😉
December 30, 2015 at 9:03 am
I am waiting on this too….
January 29, 2016 at 4:20 am
Waiting on this!
January 5, 2016 at 11:43 am
Hi Andy,
I couldn’t get “<installPackage" named tag details anywhere. Can you provide details on this. also in this tag there is no "deployRoot" attribute.
January 6, 2016 at 8:52 am
Looks like your message got truncated.
January 7, 2016 at 2:07 pm
No, its same what i typed. however i installed pkg using this url help https://developer.salesforce.com/docs/atlas.en-us.packagingGuide.meta/packagingGuide/packaging_api_introduction.htm
January 7, 2016 at 2:05 pm
Hi Andy,
I am installing a pkg using MetaData apex wrapper, with method “createMetadata” which has return type “MetadataService.SaveResult”.
So as installing a pkg took time, it throw exception “System.CalloutException: IO Exception: Read timed out”. How can i check the pkg installation status, and do some DML after that.
January 7, 2016 at 2:17 pm
Adding one more point to my last comment, “MetadataService.SaveResult” it doesn’t have any Id in its object ,so, how i can check ongoing status of process.
August 20, 2017 at 10:38 pm
Hi Andy,
I’m using described approach to automate package installation, but the problem is that our managed package have profiles included. When you install it manually using url, as the first step it asks for what profiles in your system you want to install this package. By any change, do you happen to know how to set up this profile mapping in your ant target (if possible)
August 24, 2017 at 12:29 am
The Salesforce API does not support this. The best practice is to package permission sets and then use the sf API to assign those post install.
September 24, 2018 at 11:32 pm
Hi Andy,
I’m using Apex class to automate package installation, its throwing an error as “Method does not exist or incorrect signature: void create(List) from the type MetadataService.MetadataPort”.
How do I resolve it, Please help me out.
December 15, 2018 at 1:22 pm
It looks like you have an Apex compilation error, without seeing your code base its hard to tell. Meanwhile you can study this example perhaps… https://github.com/financialforcedev/apex-mdapi/blob/master/apex-mdapi/src/classes/MetadataServiceExamples.cls#L598.
Pingback: deploying managed package to scratch org failing giving Invalid username, password, security token; or user locked out
Pingback: Retrieve Setup>Create>Packages – GrindSkills