4

Update:

First and foremost, this is all about building a proper package.xml, objects folder full of ___.object files, and profiles folder full of ___.profile files.

You do that, the rest is cake - ZIP it up and Workbench has your back.

See my further notes in the answers at https://salesforce.stackexchange.com/a/115186/17667.


Original Post:

I am finding the bar too high for first-time usage of the Salesforce Metadata API to create a few custom objects and fields.

Background:

I am in charge of setting up a Jitterbit connection from one production org to another. Before I set it up, I'll need copies of a few 4-5 source-org custom objects mirrored in the target-org, as well as copies of some of those custom objects' fields. (I tried using packages, but that didn't work because some of the objects are part of a managed package.)

Appearance on Page Layouts isn't a priority, nor is setting up any sort of special field security (easy to fix in bulk later compared to creating the fields - either "open to all" or "closed to all but sysadmins" is fine at time of creation).

As I figure out which source fields I'm actually going to need in the target, I'm basically building a list of their API names (although some will need renaming to avoid conflicts target org naming conflicts). I know I have the text-parsing skills to turn these notes into an XML representation of an object+fields without too much trouble.

Which means it feels* wasteful to build those object/field copies by hand in the target org. But that's what I'm going to do, because my ballpark estimate is 5 hours to build everything by hand, whereas I've already lost at least 8 trying to figure out "Newbie's First Metadata API Write". And I have about 5-10 hours left for this part of the project.

Still, for future reference, I'd love to be set up to do simple "create an object and its fields" operations against Salesforce orgs.

I've looked through the PDF manual and the Quick Start, but I feel like this documentation makes way too many presumptions that I already know what I'm doing with respect to setup.

  • For example, "Prerequisites" tells me to download the "Force.com WSC," but it completely skips over any instructions on what I'm supposed to do with the .jar file it links me to. I'm that noob.

So, below is an example of the kind of XML representation of a custom object that I know I could build without too much effort and would subsequently want to use for creating such an object in a target org.

My questions are:

  1. By any chance, is this XML and having the plain-old Eclipse Force.com IDE installed on my local machine sufficient for the task I want to accomplish?

    • If so, what steps am I missing to make the job happen? (I tried copying/pasting into another part of the project tree in Eclipse & saving to server / deploying. No dice.) Also, if so, skip Question #2.

    • If not, what would you say is minimum set of "for dummies" / "GUI preferred" pieces of software I need to install and configurations I need to make in addition to what I already have set up? (Win7x64, Chrome, Firefox, Eclipse+Force.com IDE)

  2. I know StackExchange isn't really for asking people, "Help me go from zero to hero in an entire development environment in a single question!" That's more the domain of tutorials & blog posts - shame on me. But I feel like the Salesforce developer community is currently missing such "Metadata API hello world" tutorials for people who are completely new to all of the tools involved (well, except to reading & writing simple Java-like code).

    If anyone is willing to help walk me through this, limited in scope to "creating a custom object with its custom fields," please let me know somehow.

    • The simpler, the better - for example, hand-typing a Salesforce session key into code right before executing it will suffice for this exercise.

    • I guess I should also mention that I don't have to use an XML like this. I could probably do enough text-parsing to build code that has the object & field names/descriptions inlined in string notation, too, if it keeps the whole solution simpler.

    • If the answer is big, maybe we can take the conversation outside StackExchange. Then once I've had my first success I'd love to help others by screenshotting the process for a blog post (my blog / your blog / a big newbie-blog like Women Code Heroes or SFDC99) and link to it here.

Of course, if there is such a tutorial out there already, my apologies and please just let me know where it is. (But remember that I already got lost even with the official "quick start!)

Thanks a million.

<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <actionOverrides>
        <actionName>Accept</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>CancelEdit</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Clone</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Delete</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Edit</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Follow</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>List</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>New</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>SaveEdit</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Tab</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>View</actionName>
        <type>Default</type>
    </actionOverrides>
    <compactLayoutAssignment>SYSTEM</compactLayoutAssignment>
    <deploymentStatus>Deployed</deploymentStatus>
    <description>zzzTestSmallObjectHasADescription</description>
    <enableActivities>false</enableActivities>
    <enableBulkApi>true</enableBulkApi>
    <enableFeeds>false</enableFeeds>
    <enableHistory>false</enableHistory>
    <enableReports>false</enableReports>
    <enableSharing>true</enableSharing>
    <enableStreamingApi>true</enableStreamingApi>
    <fields>
        <fullName>BoolCustField__c</fullName>
        <defaultValue>false</defaultValue>
        <description>ThisIsABoolCustField</description>
        <externalId>false</externalId>
        <inlineHelpText>ThisIsABoolCustField</inlineHelpText>
        <label>BoolCustField</label>
        <trackTrending>false</trackTrending>
        <type>Checkbox</type>
    </fields>
    <label>zzzTestSmallObject</label>
    <nameField>
        <label>zzzTestSmallObject Name</label>
        <type>Text</type>
    </nameField>
    <pluralLabel>zzzTestSmallObjects</pluralLabel>
    <searchLayouts/>
    <sharingModel>ReadWrite</sharingModel>
</CustomObject>
  • If you are comfortable using Ant, then the Ant Migration Tools are perhaps easier to get going with than the various IDEs. Then you need a basic package.xml file and then can pull and push the objects. Hopefully someone will post some step by step instructions to get you over the hurdle of doing this (or one of the other approaches) for the first time. – Keith C Mar 17 '16 at 17:15
  • 1
    If I understood you correctly you want to move code from one org to another, if yes you can use ant migration tool to move object. – Himanshu Mar 17 '16 at 17:16
  • 1
    I wrote this way back so this might help you. sfdcbeginner.com/salesforce-deployment-methods.html – Himanshu Mar 17 '16 at 17:18
  • Hi @KeithC - Thanks for your opinion about how it ranks in terms of simplicity. I've never used Ant and every time I try, it looks overwhelming - especially to figure out how to apply its world of general-purpose directions to a small ad-hoc task at hand like this one. So I would definitely need task-oriented step-by-step instructions. I appreciate your input so far, though! – k.. Mar 17 '16 at 17:18
  • 1
    Let us continue this discussion in chat. – Himanshu Mar 17 '16 at 17:25
4

if you have setup ant correctly you can follow below steps

  1. Create deploy folder inside c:\apache-ant\sample folder
  2. Create one package.xml and objects folder

    <?xml version="1.0" encoding="UTF-8"?>
    <Package xmlns="http://soap.sforce.com/2006/04/metadata">
      <types>
        <members>xyz__c</members>
        <name>CustomObject</name>
    </types>
    <version>35.0</version>
    </Package>
    

enter image description here

  1. create a xml file inside objects folder and name it with xyz__c.object and put your xml content which you have added as question.

  2. I assume that you have setup ant deploy in build.xml so you can run command ant deploy and it will deploy this object in your target org.

| improve this answer | |
  • 1
    Thanks so much for the hand-holding on Skype, Himanshu. I want to give all of this the attention it deserves and flesh it out with some additional tips for fellow newbies, but right now I need to get back to working on the project at hand. It looks like I am set up and good to go for this project without painful manual-creation after all - many thanks! (Note to self to include ... make sure rules like "fullName" & "relationshipName" not allowing spaces are covered.) I'll close out the question after I've had time to come back and add my comments. You're my hero today. :-D – k.. Mar 17 '16 at 20:30
  • I am glad this worked. yes I would add one more tip. while working with ant migration tool always listen to actual error which is very user friendly. thanks to salesforce! – Himanshu Mar 17 '16 at 20:42
  • I also just discovered that all I really needed was the package.xml file and the "____.object" files in a ZIP file - the Developerforce Workbench has a tool you can upload to, no ANT install needed. That said, either way I push the metadata into my org, I'm having trouble with other tools (Jitterbit, the Developerforce Workbench SOQL Query tool's picklist of fields) not being able to see the schema - they have no idea that my fields are present on the custom object. – k.. Mar 17 '16 at 21:26
0

To recap the problem at hand:

  • The "source org" has objects like Application__c with about 400 custom fields - only 40 or so we're interested in copying data from into our "target org," which a colleague had provided me in a format I could easily turn into 'field_a__c','field_b__c','field_c__c', and so on.
    • (I pre-screened the XML in the source org's application__c.object to make sure there were no surprises like formula fields dependent on other objects, etc. I took care of adding special-care fields to the target org by hand.)
    • The list from my colleague was subject to change.
  • For this situation, permissions in the "target org" were going to be simple: complete read/write/edit/delete for "Admissions" & "Sysadmin" profiles.
  • My goal: Mimimize the time to transform "source org" definitions for each field in the aforementioned string list into working fields (ready to hook Jitterbit up to) in the "target" org by using Salesforce's Metadata API.
  • My original problem: The Metadata API is a swiss army knife, and the documentation was way too complicated for me to apply to this task.

The solution:

First and foremost, this is all about building a proper package.xml, objects folder full of ___.object files, and profiles folder full of ___.profile files.

You do that, the rest is cake - ZIP it up and Workbench has your back.


For me, building this meant using a fair amount of Python:

  • salesforceobjectfilemanipulations.py to extract a copy of the <fields></fields> contents from the source-org's downloaded application__c.object file for fields of interest to my colleague (which were then given final cleanup & pasted into a new file src_application__c.object file that I intended to upload - it is this file that was behind my original question)
  • makesalesforcepackagefromobjectfiles.py to read every *.object file in a folder ...\thepackage\objects where I'd been dumping files from the previous bullet,
    • build a set of ...\thepackage\profiles\_____.profile files that gave full CRUD for Admissions/Sysadmin profiles to all objects/fields found, and
    • build a package.xml file under thepackage that included Admissions/Sysadmin profiles and all custom objects/fields found (with the proper format mostly learned here)

Lessons learned about these packages that simplifies this task greatly:

  • If I include an object in a package and simply don't mention its existing fields, they will be left alone.
  • If I include a profile in a package and simply don't mention its permissions on objects/fields, they will be left alone.
  • If an object/field already exists (matching via API name), anything that conflicts with its existing settings that I put into the package will overwrite that object's/field's settings if possible, and error out if not.

Plus these lessons:

Every custom object needs to appear as follows:
    1. In package.xml:
        <types>
            <members>MyObject__c</members>
            <members>YourObject__c</members>
            <name>CustomObject</name>
        </types>
    2. In the filename of a file (which is inside a folder called "objects" just under "package.xml"'s level):
        MyObject__c.object
    3. Inside the "MyObject__c.object" file:
        <?xml version="1.0" encoding="UTF-8"?>
        <CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
            <deploymentStatus>Deployed</deploymentStatus>
            ...(custom field tags go here)...
            <label>My Object</label>
            <nameField>
                <displayFormat>MO-{00000000}</displayFormat>
                <label>My Object Record</label>
                <type>AutoNumber</type>
            </nameField>
            <pluralLabel>My Objects</pluralLabel>
            <sharingModel>ReadWrite</sharingModel>
        </CustomObject>
    4. Inside the "Clever Profile.profile" file:
        <objectPermissions>
            <allowCreate>true</allowCreate>
            <allowDelete>true</allowDelete>
            <allowEdit>true</allowEdit>
            <allowRead>true</allowRead>
            <modifyAllRecords>true</modifyAllRecords>
            <object>MyObject__c</object>
            <viewAllRecords>true</viewAllRecords>
        </objectPermissions>


Every custom field needs to appear as follows:
    1. In package.xml:
        <types>
            <members>MyObject__c.CustomFieldAPIName__c</members>
            <members>YourObject__c.SomeOtherCustomFieldAPIName__c</members>
            <name>CustomField</name>
        </types>
    2. Inside the "MyObject__c.object" file:
        {Inside its own <fields></fields> tagset, with various property tags appropriate to that field}
    3. Inside the "Clever Profile.profile" file:
        <fieldPermissions>
            <editable>true</editable>  <--- (or false, if applicable!)
            <field>MyObject__c.CustomFieldAPIName__c</field>
            <hidden>false</hidden>
            <readable>true</readable>
        </fieldPermissions>


Every profile type needs to appear as follows:
    1. In package.xml:
        <types>
            <members>Clever Profile</members>
            <members>Some Other Profile</members>
            <name>Profile</name>
        </types>
    2. In the filename of a file (which is inside a folder called "profiles" just under "package.xml"'s level):
        Clever Profile.object <<-- Note that sysadmin is just "Admin.object" - use Eclipse to get names
    3. Inside the "Clever Profile.profile" file:
        <?xml version="1.0" encoding="utf-8"?>
        <Profile xmlns="http://soap.sforce.com/2006/04/metadata">
        ...(custom field permission tags go here)...
        ...(custom object permission tags go here)...
        </Profile>

Once I had built thepackage in Python properly, I merely had to ZIP up the folder and upload it to my "target" org at Workbench - with "Rollback on Error" checked for safety. No ANT needed.


However...

Zipping and web-browsing are annoying when you frequently make mistakes or change your mind building your package. "Uparrow-Enter" in a command window is so much nicer when working by trial and error!

That's where ANT comes in.

You have to install ANT on your local machine, and you have to edit your operating system's "PATH" so that you can, from a command window, just type ant somethingorother and the operating system will know where to find ANT's executables.

Himanshu's blog post, Item #2, Subitem C, Steps 1-5 will walk you through installation and usage.

Personally, I split from Himanshu's instructions after Step 5. I modified copies of the build.xml and build.properties files because I felt like I was less likely to forget to backspace out my username & password when they weren't surrounded by so much code.

Here's my build.xml, which I put into a sfmytest under my apache-ant install (I copied/pasted the contents of thepackage into a new folder under sfmytest called, in this case, pypkg:

<project name="My First Salesforce Ant build" default="test" basedir="." xmlns:sf="antlib:com.salesforce">

    <property file="build.properties"/>
    <property environment="env"/>

    <!-- Setting default value for username, password and session id properties to empty string 
         so unset values are treated as empty. Without this, ant expressions such as ${sf.username}
         will be treated literally.
    -->
    <condition property="sf.username" value=""> <not> <isset property="sf.username"/> </not> </condition>
    <condition property="sf.password" value=""> <not> <isset property="sf.password"/> </not> </condition>
    <condition property="sf.sessionId" value=""> <not> <isset property="sf.sessionId"/> </not> </condition>

    <taskdef resource="com/salesforce/antlib.xml" uri="antlib:com.salesforce">
        <classpath>
            <pathelement location="../ant-salesforce.jar" />            
        </classpath>
    </taskdef>

    <!-- Test out deploy and retrieve verbs for package 'pypkg' -->
    <target name="test">
        <!-- Upload the contents of the "pypkg" package -->
        <sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="pypkg" rollbackOnError="true"/>
    </target>

</project>

From there, I opened a command prompt, navigated inside of it to the sfmytest folder, and executed the command ant test (I didn't bother to change the name of the ANT command from its name in the sample file).


To fellow newbies - Hope this helps!


| improve this answer | |
  • Update: looking at the Winter '17 preview release notes, it might be the case that the requirement for a "profiles folder full of 'SOMETHING.profile' files" in the XML package being uploaded may not be necessary. It may become possible to do object & field permission assignments via Apex after creating/editing the objects/fields themselves through the Metadata API. To be seen. (Arguably, if you're already building an XML package for the Metadata API, it might be easier to throw the object/field permissions into the package rather than switch to a different tool to set permissions.) – k.. Sep 15 '16 at 16:25
  • However, this could be very useful if you don't actually have any changes to your schema to make as I did in this Question, and all you need to do is quickly make a bunch of object/field permissions changes to a certain profile. Could be faster to type out Apex than edit a bunch of XML. Reference under "Development -> API -> New and Changed Objects -> Changed Objects -> Profile" in the preview release notes. – k.. Sep 15 '16 at 16:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.