Newer Version Available
CRUD-Based Metadata Development
Use the CRUD-based metadata calls to create, update, or delete setup and configuration components for your organization or application. These configuration components include custom objects, custom fields, and other configuration metadata. The metadata calls mimic the behavior in the Salesforce user interface for creating, updating, or deleting components. Whatever rules apply there also apply to these calls.
- Metadata API calls are available in a separate WSDL. To download the WSDL, log into Salesforce, from Setup, enter API in the Quick Find box, then select API and click the Download Metadata WSDL link.
- After logging in, you must send Metadata API calls to the Metadata API endpoint, which has a different URL than the SOAP API. Retrieve the metadataServerUrl from the LoginResult returned by your SOAP API login() call. For more information about the SOAP API, see the SOAP API Developer Guide.
- Metadata calls are either synchronous or asynchronous. CRUD calls are synchronous in API version 30.0 and later, and similar to the API core calls the results are returned in a single call. In earlier API versions, create, update, and delete are only asynchronous, which means that the results are not immediately returned in one call.
- There are synchronous metadata calls that map to the corresponding core SOAP API synchronous calls.
- createMetadata() maps to the create() SOAP API call.
- updateMetadata() maps to the update() SOAP API call.
- deleteMetadata() maps to the delete() SOAP API call.
Java Sample for CRUD-Based Development with Synchronous Calls
This section guides you through a sample Java client application that uses CRUD-based calls. This sample application performs the following main tasks.
- Uses the MetadataLoginUtil.java class to create a Metadata connection. For more information, see Step 3: Walk Through the Java Sample Code.
- Calls createMetadata() to create a custom object. This call returns the result in one call.
- Inspects the returned SaveResult object to check if the operation succeeded, and if it didn’t, writes the component name, error message, and status code to the output.
1import com.sforce.soap.metadata.*;
2
3/**
4 * Sample that logs in and creates a custom object through the metadata API
5 */
6public class CRUDSampleCreate {
7 private MetadataConnection metadataConnection;
8
9 // one second in milliseconds
10 private static final long ONE_SECOND = 1000;
11
12 public CRUDSampleCreate() {
13 }
14
15 public static void main(String[] args) throws Exception {
16 CRUDSampleCreate crudSample = new CRUDSampleCreate();
17 crudSample.runCreate();
18 }
19
20 /**
21 * Create a custom object. This method demonstrates usage of the
22 * create() and checkStatus() calls.
23 *
24 * @param uniqueName Custom object name should be unique.
25 */
26 private void createCustomObjectSync(final String uniqueName) throws Exception {
27 final String label = "My Custom Object";
28 CustomObject co = new CustomObject();
29 co.setFullName(uniqueName);
30 co.setDeploymentStatus(DeploymentStatus.Deployed);
31 co.setDescription("Created by the Metadata API Sample");
32 co.setEnableActivities(true);
33 co.setLabel(label);
34 co.setPluralLabel(label + "s");
35 co.setSharingModel(SharingModel.ReadWrite);
36
37 // The name field appears in page layouts, related lists, and elsewhere.
38 CustomField nf = new CustomField();
39 nf.setType(FieldType.Text);
40 nf.setDescription("The custom object identifier on page layouts, related lists etc");
41 nf.setLabel(label);
42 nf.setFullName(uniqueName);
43 customObject.setNameField(nf);
44
45 SaveResult[] results = metadataConnection
46 .createMetadata(new Metadata[] { co });
47
48 for (SaveResult r : results) {
49 if (r.isSuccess()) {
50 System.out.println("Created component: " + r.getFullName());
51 } else {
52 System.out
53 .println("Errors were encountered while creating "
54 + r.getFullName());
55 for (Error e : r.getErrors()) {
56 System.out.println("Error message: " + e.getMessage());
57 System.out.println("Status code: " + e.getStatusCode());
58 }
59 }
60 }
61 }
62
63 private void runCreate() throws Exception {
64 metadataConnection = MetadataLoginUtil.login();
65 // Custom objects and fields must have __c suffix in the full name.
66 final String uniqueObjectName = "MyCustomObject__c";
67 createCustomObjectSync(uniqueObjectName);
68 }
69}Java Sample for CRUD-Based Development with Asynchronous Calls
This section guides you through a sample Java client application that uses asynchronous CRUD-based calls. This sample application performs the following main tasks:
- Uses the MetadataLoginUtil.java class to create a Metadata connection. For more information, see Step 3: Walk Through the Java Sample Code.
- Calls create() to
create a new custom object.
Salesforce returns an AsyncResult object for each component you tried to create. The AsyncResult object is updated with status information as the operation moves from a queue to completed or error state.
- Calls checkStatus() in a loop until the status value in AsyncResult indicates that the create operation is completed.
Note the error handling code that follows each API call.
1import com.sforce.soap.metadata.*;
2
3/**
4 * Sample that logs in and creates a custom object through the metadata api
5 */
6public class CRUDSample {
7 private MetadataConnection metadataConnection;
8
9 // one second in milliseconds
10 private static final long ONE_SECOND = 1000;
11
12 public CRUDSample() {
13 }
14
15 public static void main(String[] args) throws Exception {
16 CRUDSample crudSample = new CRUDSample();
17 crudSample.runCreate();
18 }
19
20 /**
21 * Create a custom object. This method demonstrates usage of the
22 * create() and checkStatus() calls.
23 *
24 * @param uniqueName Custom object name should be unique.
25 */
26 private void createCustomObject(final String uniqueName) throws Exception {
27 final String label = "My Custom Object";
28 CustomObject customObject = new CustomObject();
29 customObject.setFullName(uniqueName);
30 customObject.setDeploymentStatus(DeploymentStatus.Deployed);
31 customObject.setDescription("Created by the Metadata API Sample");
32 customObject.setLabel(label);
33 customObject.setPluralLabel(label + "s");
34 customObject.setSharingModel(SharingModel.ReadWrite);
35
36 // The name field appears in page layouts, related lists, and elsewhere.
37 CustomField nf = new CustomField();
38 nf.setType(FieldType.Text);
39 nf.setDescription("The custom object identifier on page layouts, related lists etc");
40 nf.setLabel(label);
41 nf.setFullName(uniqueName);
42 customObject.setNameField(nf);
43
44 AsyncResult[] asyncResults = metadataConnection.create(
45 new CustomObject[]{customObject});
46 if (asyncResults == null) {
47 System.out.println("The object was not created successfully");
48 return;
49 }
50
51 long waitTimeMilliSecs = ONE_SECOND;
52
53 // After the create() call completes, we must poll the results of the checkStatus()
54 // call until it indicates that the create operation has completed.
55 do {
56 printAsyncResultStatus(asyncResults);
57 waitTimeMilliSecs *= 2;
58 Thread.sleep(waitTimeMilliSecs);
59 asyncResults = metadataConnection.checkStatus(new String[]{asyncResults[0].getId()});
60 } while (!asyncResults[0].isDone());
61
62 printAsyncResultStatus(asyncResults);
63 }
64
65 private void printAsyncResultStatus(AsyncResult[] asyncResults) throws Exception {
66 if (asyncResults == null || asyncResults.length == 0 || asyncResults[0] == null) {
67 throw new Exception("The object status cannot be retrieved");
68 }
69
70 AsyncResult asyncResult = asyncResults[0]; //we are creating only 1 metadata object
71
72 if (asyncResult.getStatusCode() != null) {
73 System.out.println("Error status code: " +
74 asyncResult.getStatusCode());
75 System.out.println("Error message: " + asyncResult.getMessage());
76 }
77
78 System.out.println("Object with id:" + asyncResult.getId() + " is " +
79 asyncResult.getState());
80 }
81
82 private void runCreate() throws Exception {
83 metadataConnection = MetadataLoginUtil.login();
84 // Custom objects and fields must have __c suffix in the full name.
85 final String uniqueObjectName = "MyCustomObject__c";
86 createCustomObject(uniqueObjectName);
87 }
88}