No Results
Search Tips:
- Please consider misspellings
- Try different search keywords
Newer Version Available
Step 3: Walk Through the Java Sample Code
Once you have imported the WSDL files, you can begin building client applications that use Metadata API. The sample is a good starting point for writing your own code.
Before you run the sample, modify your project and the code to:
- Include the WSC JAR, its dependencies, and the JAR files you generated from the WSDLs.
- Update USERNAME and PASSWORD variables in the MetadataLoginUtil.login() method with your user name and password. If your current IP address isn’t in your organization's trusted IP range, you'll need to append a security token to the password.
- If you are using a sandbox, be sure to change the login URL.
Login Utility
Java users can use ConnectorConfig to connect to Enterprise, Partner, and Metadata SOAP API. MetadataLoginUtil creates a ConnectorConfig object and logs in using the Enterprise WSDL login method. Then it retrieves sessionId and metadataServerUrl to create a ConnectorConfig and connects to Metadata API endpoint. ConnectorConfig is defined in WSC.
The MetadataLoginUtil class abstracts the login code from the other parts of the sample, allowing portions of this code to be reused without change across different Salesforce APIs.
1swfobject.registerObject("clippy.codeblock-0", "9");import com.sforce.soap.enterprise.EnterpriseConnection;
2import com.sforce.soap.enterprise.LoginResult;
3import com.sforce.soap.metadata.MetadataConnection;
4import com.sforce.ws.ConnectionException;
5import com.sforce.ws.ConnectorConfig;
6
7/**
8 * Login utility.
9 */
10public class MetadataLoginUtil {
11
12 public static MetadataConnection login() throws ConnectionException {
13 final String USERNAME = "user@company.com";
14 // This is only a sample. Hard coding passwords in source files is a bad practice.
15 final String PASSWORD = "password";
16 final String URL = "https://login.salesforce.com/services/Soap/c/30.0";
17 final LoginResult loginResult = loginToSalesforce(USERNAME, PASSWORD, URL);
18 return createMetadataConnection(loginResult);
19 }
20
21 private static MetadataConnection createMetadataConnection(
22 final LoginResult loginResult) throws ConnectionException {
23 final ConnectorConfig config = new ConnectorConfig();
24 config.setServiceEndpoint(loginResult.getMetadataServerUrl());
25 config.setSessionId(loginResult.getSessionId());
26 return new MetadataConnection(config);
27 }
28
29 private static LoginResult loginToSalesforce(
30 final String username,
31 final String password,
32 final String loginUrl) throws ConnectionException {
33 final ConnectorConfig config = new ConnectorConfig();
34 config.setAuthEndpoint(loginUrl);
35 config.setServiceEndpoint(loginUrl);
36 config.setManualLogin(true);
37 return (new EnterpriseConnection(config)).login(username, password);
38 }
39}Java Sample Code for File-Based Development
The sample code logs in using the login utility. Then it displays a menu with retrieve, deploy, and exit.
The retrieve() and deploy() calls both operate on a .zip file named components.zip. The retrieve() call retrieves components from your organization into components.zip, and the deploy() call deploys the components in components.zip to your organization. If you save the sample to your computer and execute it, run the retrieve option first so that you have a components.zip file that you can subsequently deploy. After retrieve or deploy calls, it checks checkStatus() in a loop until the status value in AsyncResult indicates that the operation has completed.
The retrieve() call uses a manifest file to determine the components to retrieve from your organization. A sample package.xml manifest file follows. For more details on the manifest file structure, see Working with the Zip File. For this sample, the manifest file retrieves all custom objects, custom tabs, and page layouts.
1<?xml version="1.0" encoding="UTF-8"?>
2<Package xmlns="http://soap.sforce.com/2006/04/metadata">
3 <types>
4 <members>*</members>
5 <name>CustomObject</name>
6 </types>
7 <types>
8 <members>*</members>
9 <name>CustomTab</name>
10 </types>
11 <types>
12 <members>*</members>
13 <name>Layout</name>
14 </types>
15 <version>30.0</version>
16</Package>Note the error handling code that follows each API call.
1swfobject.registerObject("clippy.codeblock-2", "9");import java.io.*;
2import java.util.*;
3import javax.xml.parsers.*;
4import org.w3c.dom.*;
5import org.xml.sax.SAXException;
6import com.sforce.soap.metadata.*;
7
8/**
9 * Sample that logs in and shows a menu of retrieve and deploy metadata options.
10 */
11public class FileBasedDeployAndRetrieve {
12
13 private MetadataConnection metadataConnection;
14
15 private static final String ZIP_FILE = "components.zip";
16
17 // manifest file that controls which components get retrieved
18 private static final String MANIFEST_FILE = "package.xml";
19
20 private static final double API_VERSION = 29.0;
21
22 // one second in milliseconds
23 private static final long ONE_SECOND = 1000;
24
25 // maximum number of attempts to deploy the zip file
26 private static final int MAX_NUM_POLL_REQUESTS = 50;
27
28 private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
29
30 public static void main(String[] args) throws Exception {
31 FileBasedDeployAndRetrieve sample = new FileBasedDeployAndRetrieve();
32 sample.run();
33 }
34
35 public FileBasedDeployAndRetrieve() {
36 }
37
38 private void run() throws Exception {
39 this.metadataConnection = MetadataLoginUtil.login();
40
41 // Show the options to retrieve or deploy until user exits
42 String choice = getUsersChoice();
43 while (choice != null && !choice.equals("99")) {
44 if (choice.equals("1")) {
45 retrieveZip();
46 } else if (choice.equals("2")) {
47 deployZip();
48 } else {
49 break;
50 }
51 // show the options again
52 choice = getUsersChoice();
53 }
54 }
55
56 /*
57 * Utility method to present options to retrieve or deploy.
58 */
59 private String getUsersChoice() throws IOException {
60 System.out.println(" 1: Retrieve");
61 System.out.println(" 2: Deploy");
62 System.out.println("99: Exit");
63 System.out.println();
64 System.out.print("Enter 1 to retrieve, 2 to deploy, or 99 to exit: ");
65 // wait for the user input.
66 String choice = reader.readLine();
67 return choice != null ? choice.trim() : "";
68 }
69
70 private void deployZip() throws Exception {
71 byte zipBytes[] = readZipFile();
72 DeployOptions deployOptions = new DeployOptions();
73 deployOptions.setPerformRetrieve(false);
74 deployOptions.setRollbackOnError(true);
75 AsyncResult asyncResult = metadataConnection.deploy(zipBytes, deployOptions);
76 DeployResult result = waitForDeployCompletion(asyncResult.getId());
77 if (!result.isSuccess()) {
78 printErrors(result, "Final list of failures:\n");
79 throw new Exception("The files were not successfully deployed");
80 }
81 System.out.println("The file " + ZIP_FILE + " was successfully deployed\n");
82 }
83
84 /*
85 * Read the zip file contents into a byte array.
86 */
87 private byte[] readZipFile() throws Exception {
88 byte[] result = null;
89 // We assume here that you have a deploy.zip file.
90 // See the retrieve sample for how to retrieve a zip file.
91 File zipFile = new File(ZIP_FILE);
92 if (!zipFile.exists() || !zipFile.isFile()) {
93 throw new Exception("Cannot find the zip file for deploy() on path:"
94 + zipFile.getAbsolutePath());
95 }
96
97 FileInputStream fileInputStream = new FileInputStream(zipFile);
98 try {
99 ByteArrayOutputStream bos = new ByteArrayOutputStream();
100 byte[] buffer = new byte[4096];
101 int bytesRead = 0;
102 while (-1 != (bytesRead = fileInputStream.read(buffer))) {
103 bos.write(buffer, 0, bytesRead);
104 }
105
106 result = bos.toByteArray();
107 } finally {
108 fileInputStream.close();
109 }
110 return result;
111 }
112
113 /*
114 * Print out any errors, if any, related to the deploy.
115 * @param result - DeployResult
116 */
117 private void printErrors(DeployResult result, String messageHeader) {
118 DeployDetails details = result.getDetails();
119 StringBuilder stringBuilder = new StringBuilder();
120 if (details != null) {
121 DeployMessage[] componentFailures = details.getComponentFailures();
122 for (DeployMessage failure : componentFailures) {
123 String loc = "(" + failure.getLineNumber() + ", " + failure.getColumnNumber();
124 if (loc.length() == 0 && !failure.getFileName().equals(failure.getFullName()))
125 {
126 loc = "(" + failure.getFullName() + ")";
127 }
128 stringBuilder.append(failure.getFileName() + loc + ":"
129 + failure.getProblem()).append('\n');
130 }
131 RunTestsResult rtr = details.getRunTestResult();
132 if (rtr.getFailures() != null) {
133 for (RunTestFailure failure : rtr.getFailures()) {
134 String n = (failure.getNamespace() == null ? "" :
135 (failure.getNamespace() + ".")) + failure.getName();
136 stringBuilder.append("Test failure, method: " + n + "." +
137 failure.getMethodName() + " -- " + failure.getMessage() +
138 " stack " + failure.getStackTrace() + "\n\n");
139 }
140 }
141 if (rtr.getCodeCoverageWarnings() != null) {
142 for (CodeCoverageWarning ccw : rtr.getCodeCoverageWarnings()) {
143 stringBuilder.append("Code coverage issue");
144 if (ccw.getName() != null) {
145 String n = (ccw.getNamespace() == null ? "" :
146 (ccw.getNamespace() + ".")) + ccw.getName();
147 stringBuilder.append(", class: " + n);
148 }
149 stringBuilder.append(" -- " + ccw.getMessage() + "\n");
150 }
151 }
152 }
153 if (stringBuilder.length() > 0) {
154 stringBuilder.insert(0, messageHeader);
155 System.out.println(stringBuilder.toString());
156 }
157 }
158
159 private void retrieveZip() throws Exception {
160 RetrieveRequest retrieveRequest = new RetrieveRequest();
161 retrieveRequest.setApiVersion(API_VERSION);
162 setUnpackaged(retrieveRequest);
163
164 AsyncResult asyncResult = metadataConnection.retrieve(retrieveRequest);
165 asyncResult = waitForRetrieveCompletion(asyncResult);
166 RetrieveResult result =
167 metadataConnection.checkRetrieveStatus(asyncResult.getId());
168
169 // Print out any warning messages
170 StringBuilder stringBuilder = new StringBuilder();
171 if (result.getMessages() != null) {
172 for (RetrieveMessage rm : result.getMessages()) {
173 stringBuilder.append(rm.getFileName() + " - " + rm.getProblem() + "\n");
174 }
175 }
176 if (stringBuilder.length() > 0) {
177 System.out.println("Retrieve warnings:\n" + stringBuilder);
178 }
179
180 System.out.println("Writing results to zip file");
181 File resultsFile = new File(ZIP_FILE);
182 FileOutputStream os = new FileOutputStream(resultsFile);
183
184 try {
185 os.write(result.getZipFile());
186 } finally {
187 os.close();
188 }
189 }
190
191 private DeployResult waitForDeployCompletion(String asyncResultId) throws Exception {
192 int poll = 0;
193 long waitTimeMilliSecs = ONE_SECOND;
194 DeployResult deployResult;
195 boolean fetchDetails;
196 do {
197 Thread.sleep(waitTimeMilliSecs);
198 // double the wait time for the next iteration
199
200 waitTimeMilliSecs *= 2;
201 if (poll++ > MAX_NUM_POLL_REQUESTS) {
202 throw new Exception(
203 "Request timed out. If this is a large set of metadata components, " +
204 "ensure that MAX_NUM_POLL_REQUESTS is sufficient.");
205 }
206 // Fetch in-progress details once for every 3 polls
207 fetchDetails = (poll % 3 == 0);
208
209 deployResult = metadataConnection.checkDeployStatus(asyncResultId, fetchDetails);
210 System.out.println("Status is: " + deployResult.getStatus());
211 if (!deployResult.isDone() && fetchDetails) {
212 printErrors(deployResult, "Failures for deployment in progress:\n");
213 }
214 }
215 while (!deployResult.isDone());
216
217 if (!deployResult.isSuccess() && deployResult.getErrorStatusCode() != null) {
218 throw new Exception(deployResult.getErrorStatusCode() + " msg: " +
219 deployResult.getErrorMessage());
220 }
221
222 if (!fetchDetails) {
223 // Get the final result with details if we didn't do it in the last attempt.
224 deployResult = metadataConnection.checkDeployStatus(asyncResultId, true);
225 }
226
227 return deployResult;
228 }
229
230 private AsyncResult waitForRetrieveCompletion(AsyncResult asyncResult) throws Exception {
231 int poll = 0;
232 long waitTimeMilliSecs = ONE_SECOND;
233 while (!asyncResult.isDone()) {
234 Thread.sleep(waitTimeMilliSecs);
235 // double the wait time for the next iteration
236
237 waitTimeMilliSecs *= 2;
238 if (poll++ > MAX_NUM_POLL_REQUESTS) {
239 throw new Exception(
240 "Request timed out. If this is a large set of metadata components, " +
241 "ensure that MAX_NUM_POLL_REQUESTS is sufficient.");
242 }
243
244 asyncResult = metadataConnection.checkStatus(
245 new String[]{asyncResult.getId()})[0];
246 System.out.println("Status is: " + asyncResult.getState());
247 }
248
249 if (asyncResult.getState() != AsyncRequestState.Completed) {
250 throw new Exception(asyncResult.getStatusCode() + " msg: " +
251 asyncResult.getMessage());
252 }
253 return asyncResult;
254 }
255
256 private void setUnpackaged(RetrieveRequest request) throws Exception {
257 // Edit the path, if necessary, if your package.xml file is located elsewhere
258 File unpackedManifest = new File(MANIFEST_FILE);
259 System.out.println("Manifest file: " + unpackedManifest.getAbsolutePath());
260
261 if (!unpackedManifest.exists() || !unpackedManifest.isFile()) {
262 throw new Exception("Should provide a valid retrieve manifest " +
263 "for unpackaged content. Looking for " +
264 unpackedManifest.getAbsolutePath());
265 }
266
267 // Note that we use the fully quualified class name because
268 // of a collision with the java.lang.Package class
269 com.sforce.soap.metadata.Package p = parsePackageManifest(unpackedManifest);
270 request.setUnpackaged(p);
271 }
272
273 private com.sforce.soap.metadata.Package parsePackageManifest(File file)
274 throws ParserConfigurationException, IOException, SAXException {
275 com.sforce.soap.metadata.Package packageManifest = null;
276 List<PackageTypeMembers> listPackageTypes = new ArrayList<PackageTypeMembers>();
277 DocumentBuilder db =
278 DocumentBuilderFactory.newInstance().newDocumentBuilder();
279 InputStream inputStream = new FileInputStream(file);
280 Element d = db.parse(inputStream).getDocumentElement();
281 for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling()) {
282 if (c instanceof Element) {
283 Element ce = (Element) c;
284 NodeList nodeList = ce.getElementsByTagName("name");
285 if (nodeList.getLength() == 0) {
286 continue;
287 }
288 String name = nodeList.item(0).getTextContent();
289 NodeList m = ce.getElementsByTagName("members");
290 List<String> members = new ArrayList<String>();
291 for (int i = 0; i < m.getLength(); i++) {
292 Node mm = m.item(i);
293 members.add(mm.getTextContent());
294 }
295 PackageTypeMembers packageTypes = new PackageTypeMembers();
296 packageTypes.setName(name);
297 packageTypes.setMembers(members.toArray(new String[members.size()]));
298 listPackageTypes.add(packageTypes);
299 }
300 }
301 packageManifest = new com.sforce.soap.metadata.Package();
302 PackageTypeMembers[] packageTypesArray =
303 new PackageTypeMembers[listPackageTypes.size()];
304 packageManifest.setTypes(listPackageTypes.toArray(packageTypesArray));
305 packageManifest.setVersion(API_VERSION + "");
306 return packageManifest;
307 }
308}