Running the Apex Data Loader on a Mac

Even though the Apex Data Loader is written in Java it doesn’t work on a Mac for two main reasons:

  • It is packaged in a Windows-only installer
  • Instead of using Swing for its GUI that does not require any platform-specific code to be included in the application it uses SWT that does require platform-specific code

The first problem can be worked around by installing on a Windows machine first and then copying the installation across to the Mac.

The second problem can be worked around using these steps (assuming you have a working copy of the Eclipse IDE on your Mac perhaps to make use of the Force IDE):

  • Copy the files that start org.eclipse.swt (e.g. org.eclipse.swt_3.6.1.v3655c.jar and org.eclipse.swt.cocoa.macosx.x86_64_3.6.1.v3655c.jar) from eclipse/plugins to the directory that contains DataLoader.jar (that you copied across from Windows).
  • Use this command-line (using the file names from the previous step) to run the DataLoader:
    java -Dsalesforce.config.dir=conf -XstartOnFirstThread -cp org.eclipse.swt_3.6.1.v3655c.jar:org.eclipse.swt.cocoa.macosx.x86_64_3.6.1.v3655c.jar:DataLoader.jar com.salesforce.dataloader.process.DataLoaderRunner

The -D argument specifies the location of the configuration files, the -X argument appears to be required for this version of SWT to work, the -cp argument gives priority to the Mac version of the SWT classes ahead of the Windows versions included in DataLoader.jar and the last argument is the name of the class that launches the GUI.

If you choose to run the data loader like this obviously Salesforce will not support you and you should be cautious and check your results carefully. Also consider using LexiLoader – see comments below.

Advertisements

Scripting the Apex Data Loader via Ant

The Apex Data Loader can be scripted using Spring bean XML definitions. Where the configuration needs to vary for each object that approach makes sense. But I had a need to (repeatedly) export many different objects with largely the same configuration and so wanted to use Ant and keep the configuration in Ant.

The resulting Ant build.xml file is shown here, where a macro is used that accepts a file name, an object name and a SOQL string, making it simple to add additional object exports as needed:

<?xml version="1.0" encoding="UTF-8"?>
<project name="Export" default="all">
    <macrodef name="export">
        <attribute name="file"/>
        <attribute name="object"/>
        <attribute name="soql"/>
        <sequential>
            <echo message="Exporting @{object}"/>
            <mkdir dir="exports"/>
            <copy file="config/template-process-conf.xml" tofile="config/process-conf.xml" overwrite="true" failonerror="true"/>
            <replace file="config/process-conf.xml">
                <replacefilter token="_object_" value="@{object}"/>
                <replacefilter token="_soql_" value="@{soql}"/>
                <replacefilter token="_file_" value="exports/@{file}.csv"/>
            </replace>
            <java classname="com.salesforce.dataloader.process.ProcessRunner" classpath="lib/DataLoader.jar" failonerror="true">
                <sysproperty key="salesforce.config.dir" value="config"/>
                <arg line="process.name=@{object}"/>
            </java>
        </sequential>
    </macrodef>
    <target name="all">
        <export file="SampleAccounts" object="Account" soql="Select Id, Name, ... From Account"/>
        <export file="SampleContacts" object="Contact" soql="Select Id, Name, ... From Contact"/>
        ...
    </target>
</project>

The Ant macro is replacing tokens in this template-process-conf.xml file to produce a process-conf.xml file for each object export:

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="_object_" class="com.salesforce.dataloader.process.ProcessRunner" singleton="false">
        <description>TemplatedCsvExtract extracts to a CSV file."</description>
        <property name="name" value="TemplatedCsvExtract"/>
        <property name="configOverrideMap">
            <map>
                <entry key="sfdc.endpoint" value="..."/>
                <entry key="sfdc.username" value="..."/>
                <entry key="sfdc.password" value="..."/>
                <entry key="sfdc.debugMessages" value="false"/>
                <entry key="sfdc.timeoutSecs" value="600"/>
                <entry key="sfdc.extractionRequestSize" value="500"/>
                <entry key="process.operation" value="extract"/>
                <entry key="dataAccess.type" value="csvWrite"/>
                <entry key="sfdc.entity" value="_object_"/>
                <entry key="sfdc.extractionSOQL" value="_soql_"/>
                <entry key="dataAccess.name" value="_file_"/>
            </map>
        </property>
    </bean>
</beans>

The directories required are:

  • “config” containing the template-process-conf.xml file, an empty config.properties file and a log-conf.xml file
  • “lib” containing a copy of DataLoader.jar so that Ant can invoke its com.salesforce.dataloader.process.ProcessRunner class

The output CSV files are written to the “exports” folder.

PS I was working with this again recently on a different machine than the encrypt utility was run on. So as well as setting “sfdc.password” to be the encrypted version of the password and security token I also needed to set the “process.encryptionKeyFile” to reference a file containing the key used to encrypt the password.