Newer Version Available

This content describes an older version of this product. View Latest

deploy()

Uses file representations of components to create, update, or delete those components in an organization.

Syntax

1AsyncResult = metadatabinding.deploy(base64 zipFile, DeployOptions deployOptions)

Usage

Use this call to take file representations of components and deploy them into an organization by creating, updating, or deleting the components they represent.

Metadata API can deploy and retrieve up to 5,000 files at one time. While a specific file size limit is not enforced, you might encounter out-of-memory errors for very large files.

Note

In API version 29.0, Salesforce improved the deployment status properties and removed the requirement to use checkStatus() after a deploy() call to get information about deployments. Salesforce continues to support the use of checkStatus() when using deploy() with API version 28.0 or earlier.

For API version 29.0 or later, deploy (create or update) packaged or unpackaged components using the following steps.

  1. Issue a deploy() call to start the asynchronous deployment. An AsyncResult object is returned. Note the value in the id field and use it for the next step.
  2. Issue a checkDeployStatus() call in a loop until the done field of the returned DeployResult contains true, which means that the call is completed. The DeployResult object contains information about an in-progress or completed deployment started using the deploy() call. When calling checkDeployStatus(), pass in the id value from the AsyncResult object from the first step.

For API version 28.0 or earlier, deploy (create or update) packaged or unpackaged components using the following steps.

  1. Issue a deploy() call to start the asynchronous deployment. An AsyncResult object is returned. If the call is completed, the done field contains true. Most often, the call is not completed quickly enough to be noted in the first result. If it is completed, note the value in the id field returned and skip the next step.
  2. If the call is not complete, issue a checkStatus() call in a loop using the value in the id field of the AsyncResult object returned by the deploy() call in the previous step. Check the AsyncResult object which is returned until the done field contains true. The time taken to complete a deploy() call depends on the size of the zip file being deployed, so a longer wait time between iterations should be used as the size of the zip file increases.
  3. Issue a checkDeployStatus() call to obtain the results of the deploy() call, using the id value returned in the first step.

To delete items, use the same procedure, but also include a delete manifest file named destructiveChanges.xml. To bypass the Recycle Bin, see purgeOnDelete.

The format of destructiveChanges.xml is the same as package.xml, except that wildcards are not supported.

If you try to delete some components that do not exist in the organization, the rest of the deletions are still attempted.

Note

The following is a sample destructiveChanges.xml file that names a single custom object to be deleted:

1<?xml version="1.0" encoding="UTF-8"?>
2<Package xmlns="http://soap.sforce.com/2006/04/metadata">
3    <types>
4        <members>MyCustomObject__c</members>
5        <name>CustomObject</name>
6    </types>
7</Package>

In order to deploy the destructive changes, you must also have a package.xml file that lists no components to deploy, includes the API version, and is in the same directory as destructiveChanges.xml:

1<?xml version="1.0" encoding="UTF-8"?>
2<Package xmlns="http://soap.sforce.com/2006/04/metadata">
3    <version>30.0</version>
4</Package>

To track the status of deployments that are in progress or completed in the last 30 days, from Setup, click Deployment Status or Deploy | Deployment Status.

You can cancel a deployment while it’s in progress or in the queue by clicking Cancel next to the deployment. The deployment then has the status Cancel Requested until the deployment is completely canceled. A canceled deployment is listed in the Failed section.

Permissions

Your client application must be logged in with the “Modify All Data” permission.

Arguments

Name Type Description
zipFile base64 Base 64-encoded binary data. Client applications must encode the binary data as base64.
deployOptions DeployOptions Encapsulates options for determining which packages or files are deployed.

DeployOptions

The following deployment options can be selected for this call:

Name Type Description
allowMissingFiles boolean Specifies whether a deploy succeeds even if files that are specified in package.xml but are not in the .zip file (true or not false).

Do not set this argument for deployment to production organizations.

autoUpdatePackage boolean If a file is in the .zip file but not specified in package.xml, specifies whether the file should be automatically added to the package (true or not false). A retrieve() is automatically issued with the updated package.xml that includes the .zip file.

Do not set this argument for deployment to production organizations.

checkOnly boolean Indicates whether Apex classes and triggers are saved to the organization as part of the deployment (false) or not (true). Defaults to false. Any errors or messages that would have been issued are still generated. This parameter is similar to the Salesforce Ant tool’s checkOnly parameter.
ignoreWarnings boolean Indicates whether a warning should allow a deployment to complete successfully (true) or not (false). Defaults to false.

The DeployMessage object for a warning contains the following values:

  • problemTypeWarning
  • problem—The text of the warning.

If a warning occurs and ignoreWarnings is set to true, the success field in DeployMessage is true. If ignoreWarnings is set to false, success is set to false and the warning is treated like an error.

This field is available in API version 18.0 and later. Prior to version 18.0, there was no distinction between warnings and errors. All problems were treated as errors and prevented a successful deployment.

performRetrieve boolean Indicates whether a retrieve() call is performed immediately after the deployment (true) or not (false). Set to true in order to retrieve whatever was just deployed.
purgeOnDelete boolean If true, the deleted components in the destructiveChanges.xml manifest file aren't stored in the Recycle Bin. Instead, they become immediately eligible for deletion.

This field is available in API version 22.0 and later.

This option only works in Developer Edition or sandbox organizations; it doesn't work in production organizations.

rollbackOnError boolean Indicates whether any failure causes a complete rollback (true) or not (false). If false, whatever set of actions can be performed without errors are performed, and errors are returned for the remaining actions. This parameter must be set to true if you are deploying to a production organization. The default is false.
runAllTests boolean If true, all Apex tests defined in the organization are run.

For deployment to a production organization, all tests, except for those that originate from installed managed packages, are automatically run regardless of this argument. If any of the tests fail when the rollbackOnError parameter is set to true, the entire deployment will roll back.

runTests string[] A list of Apex tests to be run during deployment. Specify the class name, one name per instance. The class name may also specify a namespace with a dot. For example, to run three tests:
1<runTests>positive_test</runTests>
2<runTests>negative_test</runTests>
3<runTests>namespace.third_test</runTests>

If any of these tests fail when the rollbackOnError parameter is set to true, the deployment is rolled back and no changes will be made to your organization.

singlePackage boolean Indicates whether the specified .zip file points to a directory structure with a single package (true) or a set of packages (false).

Response

AsyncResult

Sample Code—Java

This sample shows how to deploy components in a zip file. See the retrieve() sample code for details on how to retrieve a zip file.

1swfobject.registerObject("clippy.codeblock-4", "9");package com.doc.samples;
2
3import java.io.*;
4
5import java.rmi.RemoteException;
6
7import com.sforce.soap.metadata.AsyncResult;
8import com.sforce.soap.metadata.DeployDetails;
9import com.sforce.soap.metadata.MetadataConnection;
10import com.sforce.soap.metadata.DeployOptions;
11import com.sforce.soap.metadata.DeployResult;
12import com.sforce.soap.metadata.DeployMessage;
13import com.sforce.soap.metadata.RunTestsResult;
14import com.sforce.soap.metadata.RunTestFailure;
15import com.sforce.soap.metadata.CodeCoverageWarning;
16import com.sforce.soap.partner.LoginResult;
17import com.sforce.soap.partner.PartnerConnection;
18import com.sforce.ws.ConnectionException;
19import com.sforce.ws.ConnectorConfig;
20
21/**
22 * Deploy a zip file of metadata components. 
23 * Prerequisite: Have a deploy.zip file that includes a package.xml manifest file that 
24 * details the contents of the zip file.
25 */
26public class DeploySample {
27    // binding for the metadata WSDL used for making metadata API calls
28    private MetadataConnection metadataConnection;
29
30    static BufferedReader rdr = new BufferedReader(new InputStreamReader(System.in));
31
32    private static final String ZIP_FILE = "deploy.zip";
33
34    // one second in milliseconds
35    private static final long ONE_SECOND = 1000;
36    // maximum number of attempts to deploy the zip file
37    private static final int MAX_NUM_POLL_REQUESTS = 50; 
38
39    public static void main(String[] args) throws Exception {
40        final String USERNAME = "user@company.com";
41        // This is only a sample. Hard coding passwords in source files is a bad practice.
42        final String PASSWORD = "password"; 
43        final String URL = "https://login.salesforce.com/services/Soap/u/29.0";
44        
45        DeploySample sample = new DeploySample(USERNAME, PASSWORD, URL);
46        sample.deployZip();
47    }
48    
49    public DeploySample(String username, String password, String loginUrl) throws ConnectionException {
50        createMetadataConnection(username, password, loginUrl);
51    }
52
53    public void deployZip()
54        throws RemoteException, Exception
55    {
56        byte zipBytes[] = readZipFile();
57        DeployOptions deployOptions = new DeployOptions();
58        deployOptions.setPerformRetrieve(false);
59        deployOptions.setRollbackOnError(true);
60        AsyncResult asyncResult = metadataConnection.deploy(zipBytes, deployOptions);
61        String asyncResultId = asyncResult.getId();
62        
63        // Wait for the deploy to complete
64        int poll = 0;
65        long waitTimeMilliSecs = ONE_SECOND;
66        DeployResult deployResult = null;
67        boolean fetchDetails;
68        do {
69            Thread.sleep(waitTimeMilliSecs);
70            // double the wait time for the next iteration
71            waitTimeMilliSecs *= 2;
72            if (poll++ > MAX_NUM_POLL_REQUESTS) {
73                throw new Exception("Request timed out. If this is a large set " +
74                        "of metadata components, check that the time allowed by " +
75                        "MAX_NUM_POLL_REQUESTS is sufficient.");
76            }
77            
78            // Fetch in-progress details once for every 3 polls
79            fetchDetails = (poll % 3 == 0);
80            deployResult = metadataConnection.checkDeployStatus(asyncResultId, fetchDetails);
81            System.out.println("Status is: " + deployResult.getStatus());
82            if (!deployResult.isDone() && fetchDetails) {
83                printErrors(deployResult, "Failures for deployment in progress:\n");
84            }
85        }
86        while (!deployResult.isDone());
87        
88        if (!deployResult.isSuccess() && deployResult.getErrorStatusCode() != null) {
89            throw new Exception(deployResult.getErrorStatusCode() + " msg: " +
90                    deployResult.getErrorMessage());
91        }
92
93        if (!fetchDetails) {
94            // Get the final result with details if we didn't do it in the last attempt.
95            deployResult = metadataConnection.checkDeployStatus(asyncResultId, true);
96        }
97
98        if (!deployResult.isSuccess()) {
99            printErrors(deployResult, "Final list of failures:\n");
100            throw new Exception("The files were not successfully deployed");
101        }
102        
103        System.out.println("The file " + ZIP_FILE + " was successfully deployed");
104    }
105    
106    /**
107     * Read the zip file contents into a byte array.
108     * @return byte[]
109     * @throws Exception - if cannot find the zip file to deploy
110     */
111    private byte[] readZipFile()
112        throws Exception
113    {
114        // We assume here that you have a deploy.zip file.
115        // See the retrieve sample for how to retrieve a zip file.
116        File deployZip = new File(ZIP_FILE);
117        if (!deployZip.exists() || !deployZip.isFile())
118            throw new Exception("Cannot find the zip file to deploy. Looking for " +
119                    deployZip.getAbsolutePath());
120        
121        FileInputStream fos = new FileInputStream(deployZip);
122        ByteArrayOutputStream bos = new ByteArrayOutputStream();
123        int readbyte = -1;
124        while ((readbyte = fos.read()) != -1)  {
125            bos.write(readbyte);
126        }
127        fos.close();
128        bos.close();
129        return bos.toByteArray();
130    }
131    
132 
133    /**
134     * Print out any errors, if any, related to the deploy.
135     * @param result - DeployResult
136     */
137    private void printErrors(DeployResult result, String messageHeader)
138    {
139        DeployDetails deployDetails = result.getDetails();
140        
141        StringBuilder errorMessageBuilder = new StringBuilder();
142        if (deployDetails != null) {
143            DeployMessage[] componentFailures = deployDetails.getComponentFailures();
144            for (DeployMessage message : componentFailures) {
145                String loc = (message.getLineNumber() == 0 ? "" :
146                    ("(" + message.getLineNumber() + "," +
147                            message.getColumnNumber() + ")"));
148                if (loc.length() == 0
149                        && !message.getFileName().equals(message.getFullName())) {
150                    loc = "(" + message.getFullName() + ")";
151                }
152                errorMessageBuilder.append(message.getFileName() + loc + ":" +
153                        message.getProblem()).append('\n');
154            }
155            RunTestsResult rtr = deployDetails.getRunTestResult();
156            if (rtr.getFailures() != null) {
157                for (RunTestFailure failure : rtr.getFailures()) {
158                    String n = (failure.getNamespace() == null ? "" :
159                        (failure.getNamespace() + ".")) + failure.getName();
160                    errorMessageBuilder.append("Test failure, method: " + n + "." +
161                            failure.getMethodName() + " -- " +
162                            failure.getMessage() + " stack " +
163                            failure.getStackTrace() + "\n\n");
164                }
165            }
166            if (rtr.getCodeCoverageWarnings() != null) {
167                for (CodeCoverageWarning ccw : rtr.getCodeCoverageWarnings()) {
168                    errorMessageBuilder.append("Code coverage issue");
169                    if (ccw.getName() != null) {
170                        String n = (ccw.getNamespace() == null ? "" :
171                            (ccw.getNamespace() + ".")) + ccw.getName();
172                        errorMessageBuilder.append(", class: " + n);
173                    }
174                    errorMessageBuilder.append(" -- " + ccw.getMessage() + "\n");
175                }
176            }
177        }
178        
179        if (errorMessageBuilder.length() > 0) {
180            errorMessageBuilder.insert(0, messageHeader);
181            System.out.println(errorMessageBuilder.toString());
182        }
183    }
184    
185    private void createMetadataConnection( 
186        final String username,
187        final String password,
188        final String loginUrl) throws ConnectionException {
189
190        final ConnectorConfig loginConfig = new ConnectorConfig();
191        loginConfig.setAuthEndpoint(loginUrl);
192        loginConfig.setServiceEndpoint(loginUrl);
193        loginConfig.setManualLogin(true);
194        LoginResult loginResult = (new PartnerConnection(loginConfig)).login(username, password);
195        
196        final ConnectorConfig metadataConfig = new ConnectorConfig();
197        metadataConfig.setServiceEndpoint(loginResult.getMetadataServerUrl());
198        metadataConfig.setSessionId(loginResult.getSessionId());
199        this.metadataConnection = new MetadataConnection(metadataConfig);
200    }
201
202}