Wednesday, November 27, 2013

InvalidSObjectFault INVALID_TYPE

Today, I spent a while trying to figure out why my calls to get an object via the Partner API failed.

In code I composed a query, just like usual, and made the call, just like usual but I got this error

[InvalidSObjectFault [ApiQueryFault [ApiFault  
    exceptionCode='INVALID_TYPE' 
    exceptionMessage='Select ... FROM MyCustomObject__c ...'

    sObject type 'MyCustomObject__c' is not supported. If you are attempting to use a custom object, be sure to append the '__c' after the entity name. Please reference your WSDL or the describe call for the appropriate names.']

A searched for help on "InvalidSObjectFault" is frustrating and didn't help. The object "MyCustomObject__c" is valid. I could run the same query in the SoqlXplorer (http://www.pocketsoap.com/osx/soqlx ).  So I could easily verify the query was good. I retrieved the object class files and inspected them without any clue. Next I used my other posting about rebuilding the partner jar file to get the latest V29, just in case this was a versioning issue. 

Nothing.

Turns out the solution is simple yet the error message sends you completely way off base.

Solution

Check the user's profile permissions on the object. If the user does not have permission then API responds with InvalidSObjectFault.

(Why couldn't the description of this fault include the fact that the sObject may be valid yet the user lacks permission?)

Wednesday, April 3, 2013

Using the new Salesforce Geolocation Fields

I started with all the links I could find on Google
https://help.salesforce.com/HTSearchResults?qry=geolocation+soql
https://help.salesforce.com/HTViewSolution?id=000159817&language=en_US
https://help.salesforce.com/HTViewSolution?id=000171328&language=en_US
http://salesforce.stackexchange.com/questions/388/geolocation-searching
http://blogs.developerforce.com/engineering/2012/06/new-geolocation-features-and-mobile-apps.html

The best sample query I could find was from that last link:
SELECT name__c, phone__c
FROM restaurant__c
WHERE DISTANCE(loc__c, GEOLOCATION(37.794915,-122.394733), "mi") <= 1


 But the above did not work.  Problem?  As documented elsewhere the query only supports < or > not <=.  The correct query is:

SELECT name__c, phone__c
FROM restaurant__c
WHERE DISTANCE(loc__c, GEOLOCATION(37.794915,-122.394733), "mi") < 1



Another link that shows the correct query was found later. See
http://www.salesforce.com/us/developer/docs/soql_sosl/

Testing Queries


Next I found that my copy of SOQLExplorer doesn't support these queries at all.   I'll have to update my MAC operating system to update to the latest SOQLExplore.   But we can test these queries using the developer console.   Log onto Salesforce. Select your Name. In the drop down select Developer Console.

In the console use the Query Editor.

Using Geolocation with Partner API Queries

Next I found that my older version of the partner API does not support these queries either.  That made me try to rebuild the partner.api.  See previous posting
http://sforcehacks.blogspot.ca/2013/04/building-partnerjar-api-file.html

I'll see if this works and then come back and update this posting.

Building the Partner.jar API file

The SF documentation is missing some information needed to build the latest partner.jar API file.  Here is the link I found that gets you started
http://www.salesforce.com/us/developer/docs/api_asynch/Content/asynch_api_code_set_up_client.htm

The missing part is a dependency on a Javascript libraray called rhino.  If you follow the instructions given you get

~/Documents/workspace2/salesforce/carmanah_salesforce$ java -classpath force-wsc-27.0.0.jar com.sforce.ws.tools.wsdlc partner.wsdl partner-27.jar
[WSC][wsdlc.run:320]Created temp dir: /var/folders/D0/D0me7a5vFGmGh95S1IO9PU+++TI/-Tmp-/wsdlc-temp-3884699697501788635-dir
[WSC][wsdlc.<init>:81]Generating Java files from schema ...
Exception in thread "main" java.lang.NoClassDefFoundError: org/mozilla/javascript/Scriptable
    at com.sforce.ws.tools.TypeGenerator.generate(TypeGenerator.java:73)
    at com.sforce.ws.tools.wsdlc.generate(wsdlc.java:291)
    at com.sforce.ws.tools.wsdlc.generateTypes(wsdlc.java:278)
    at com.sforce.ws.tools.wsdlc.<init>(wsdlc.java:81)
    at com.sforce.ws.tools.wsdlc.run(wsdlc.java:320)
    at com.sforce.ws.tools.wsdlc.main(wsdlc.java:311)
Caused by: java.lang.ClassNotFoundException: org.mozilla.javascript.Scriptable
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    ... 6 more

The solution is to get the latest rhino library from http://mvnrepository.com/artifact/rhino
and add this to the command line.

Just for the record, the WSC download is here http://mvnrepository.com/artifact/com.force.api/force-wsc
I'm working with v27 today,  file: "force-wsc-27.0.0.jar"
I also downloaded rhino jar file: "js-1.7R2.jar"

I am working on a MAC. I placed both downloaded jar files in my working directory.  I downloaded the partner.wsdl file as well.  Then use this command line to produce the partner jar file:

java -classpath force-wsc-27.0.0.jar:js-1.7R2.jar com.sforce.ws.tools.wsdlc partner.wsdl partner-27.jar

On some systems you need to use a semi-colon to separate the jar files. Like this:
java -classpath force-wsc-27.0.0.jar;js-1.7R2.jar com.sforce.ws.tools.wsdlc partner.wsdl partner-27.jar



Thursday, February 28, 2013

Using the Migration Tool - Part 2

This post is a continuation of Working Sandbox and Production Using the Force Migration Tool
This post assumes we have made the build.xml file described in that posting.

Using the Ant Force.com Migration Tool:

  • I'll show you how to perform a typical retrieve from Production; deploy to Sandbox; fix; deploy to Sandbox and test; then deploy to Producton. 
  • Then I'll show you how to create a new APEX  Class.
  • Then I'll show you how to create a new APEX Trigger.

Typical workflow to fix something on Production.  

  1. Edit the workArea/package.xml file to specify what classes, triggers or object I need to fix. See this post for more how to do this.
  2. Run the ant tool to retrieve from production.  
    1. ant -v -lib . -f build.xml -Dtarget=prod retrieve
  3. Run the ant tool to deploy to the sandbox.   
    1. ant -v -lib . -f build.xml -Dtarget=test deploy
  4. Assuming the deploy worked it is now time to fix what you need to fix.  Include test cases verify your fix and provide the 75+% test coverage required by Salesforce.  Strive for 90% coverage.
  5. Run the ant tool to deploy to the sandbox.  Test cases will run to validate your fix.
    1. ant -v -lib . -f build.xml -Dtarget=test deploy
  6. Run the ant tool to deploy to production.
    1. ant -v -lib . -f build.xml -Dtarget=prod deploy
Nice and clean.


Here is the complete build file:

<project name="Salesforce Project"  default="work" basedir="." xmlns:sf="antlib:com.salesforce">
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>

<target name="setup" >
  <!-- on command line include "-DtargetDir=src" to change the target -->
  <property name="targetDir"  value="workarea" />
  <if>
   <equals arg1="${target}" arg2="test" />
   <then>
     <property file="buildTest.properties"/>
     <property name="system"  value="TEST" />
   </then>
   <elseif>
    <equals arg1="${target}" arg2="prod" />
    <then>
     <property file="buildProd.properties"/>
     <property name="system"  value="PROD" />
    </then>
   </elseif>
   <else>
     <echo message="The value of property target is not 'test' or 'prod'" level="error" />
     <fail/>
   </else>
  </if>
</target>

<target name="work"  depends="setup">
   <echo>The ${system} user name is ${sf.username}</echo>
</target>


<!-- Retrieve an unpackaged set of metadata from your org -->
<!-- The file ${targetDir}/package.xml lists what is to be retrieved -->
<target name="retrieve" depends="setup">
   <!-- Retrieve the contents into another directory -->
   <sf:retrieve username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" retrieveTarget="${targetDir}" unpackaged="${targetDir}/package.xml"/>
</target>

<!-- Deploy the unpackaged set of metadata retrieved with retrieveUnpackaged -->
<!-- The file ${targetDir}/package.xml lists what is to be depployed -->
<target name="deploy" depends="setup">
   <sf:deploy username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" deployRoot="${targetDir}"/>
</target>

</project>



Create APEX Class Using Ant

So here is a snippet to include in your build.xml file to generate a blank APEX class.

<!--
Sample: Create an after upsert trigger on object Opportunity
    ant -v -lib . -f build.xml -Dtarget=test -DclassName=Foo -Dtype=after createClass
Results:
Two files:
Foo.cls
Foo.cls-meta.xml

-->
<target name="createClass" depends="setup" >
    <fail unless="className" message="Must provide className (-DclassName=Foo) "/>
    <mkdir dir="${targetDir}/classes"/>
    <echo file="${targetDir}/classes/${className}.cls" append="false">public with sharing class ${className} {
}</echo>
    <copy file="templates/classes.meta.xml"  tofile="${targetDir}/triggers/${className}.cls-meta.xml" />
</target>
 


Before running this create a directory for the templates

~/Documents/salesforce/dev$ mkdir templates/

Then create the file classes.meta.xml  and insert the following:

<?xml version="1.0" encoding="UTF-8"?>
<ApexClasses xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>26.0</apiVersion>
    <status>Active</status>
</
ApexClasses>


Now when you run ant like this
ant -v -lib . -f build.xml -Dtarget=test -Dobject=Opportunity -Dtype=after createTrigger

you get triggers/OpportunityAfterUpsertTrigger.trigger  with this content

trigger OpportunityAfterUpsertTrigger on Opportunity (after insert, after update) {
}


and you get   triggers/OpportunityAfterUpsertTrigger.trigger-meta.xml  with the necessary meta definition.  When you deploy this new class will be pushed to the server.




Create APEX Trigger Using Ant

I have a simple naming convention for my trigger files.   Object + Before or After + "UpsertTrigger".  For example  OpportunityAfterUpsertTrigger works on Opportunity objects after insert or update.    I generally only build before or after upsert triggers; meaning I generally have triggers like this
trigger OpportunityAfterUpsertTrigger on Opportunity (after insert, after update) {
}

or this
trigger OpportunityBeforeUpsertTrigger on Opportunity (before insert, before update) {
}


Inside these triggers I generally collect the objects that need to be worked on and ship them over to another class to do the work and testing.

So here is a snippet to include in your build.xml file to generate a blank trigger. 

<!--
Sample: Create an after upsert trigger on object Opportunity
    ant -v -lib . -f build.xml -Dtarget=test -Dobject=Opportunity -Dtype=after createTrigger
Results:
Two files:
OpportunityAfterUpsertTrigger.trigger
OpportunityAfterUpsertTrigger.trigger-meta.xml

-->
<target name="createTrigger" depends="setup" >
    <fail unless="object" message="Must provide Object for the trigger"/>
    <fail unless="type" message="Must provide type 'before' or 'after' "/>
    <if>
    <equals arg1="${type}" arg2="before" />
    <then>
            <property name="triggerName" value="${object}BeforeUpsertTrigger" />
    </then>
    <elseif>
    <equals arg1="${type}" arg2="after" />
    <then>
            <property name="triggerName" value="${object}AfterUpsertTrigger" />
    </then>
    </elseif>
    <else>
     <echo message="The value of property type is not 'before' or 'after'" level="error" />
     <fail/>
    </else>
    </if>
    <mkdir dir="${targetDir}/triggers"/>
    <echo file="${targetDir}/triggers/${triggerName}.trigger" append="false">trigger ${triggerName} on ${object}</echo>
    <if> <equals arg1="${type}" arg2="before" />
    <then>
        <echo file="${targetDir}/triggers/${triggerName}.trigger" append="true"> (before insert, before update) {
}</echo>
    </then>
    <elseif> <equals arg1="${type}" arg2="after" />
    <then>
        <echo file="${targetDir}/triggers/${triggerName}.trigger" append="true"> (after insert, after update) {
}</echo>
    </then>
    </elseif>
    </if>
  
    <copy file="templates/trigger.meta.xml"  tofile="${targetDir}/triggers/${triggerName}.trigger-meta.xml" />
 
</target>


Before running this create a directory for the templates

~/Documents/salesforce/dev$ mkdir templates/

Then create the file trigger.meta.xml  and insert the following:

<?xml version="1.0" encoding="UTF-8"?>
<ApexTrigger xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>26.0</apiVersion>
    <status>Active</status>
</ApexTrigger>



Now when you run ant like this
ant -v -lib . -f build.xml -Dtarget=test -Dobject=Opportunity -Dtype=after createTrigger

you get triggers/OpportunityAfterUpsertTrigger.trigger  with this content

trigger OpportunityAfterUpsertTrigger on Opportunity (after insert, after update) {
}


and you get   triggers/OpportunityAfterUpsertTrigger.trigger-meta.xml  with the necessary meta definition.  When you deploy this new class will be pushed to the server.










Working Sandbox and Production Using the Force Migration Tool


 Easily Switch Between Sandbox and Production  Using the Force Migration Tool

This is a continuation of my previous post Getting Started with Salesforce Ant Migration with Force.com IDE

I'll show you how to create ant build scripts to easily switch between a Sandbox and Production.   I'm using a Mac so Window's users will need to make a few adjustments.

The Ant Migration Tool is significantly faster that using the Force.com IDE.   So, I am beginning to use the command line tool more and the Force.com IDE less.  What I need is an easy way to work with a project and have it quickly switch between a Sandbox and the main Production instance of Salesforce.


At first this is easy enough:  I just need to have two build.properties files. One for the sandbox and the other for production.  Then, keeping it simple, I create two build.xml files that are identical except one uses the sandbox properties and the other uses the production.

Simple, but clearly not a scalable solution.  So, how can I do this better?  By using some form of if-then-else condition processing.   Note, once a property is set in Ant it can not be modified.

Google search locates this answer:
http://stackoverflow.com/questions/5116619/apache-ant-if-then-else-task

Contributors provide two answers.  One uses built in Ant tasks that can do one thing or another.  But, I find that approach difficult to understand and would prefer a more classic "if-then-else" solution.  Further down in the post is another answer that uses a module that needs to be downloaded into your system.   This module provides more than just if-then-else so I feel it is worth the extra effort.

Download, Install and Use the Contrib Module


You can read about what the contrib module provides here
http://ant-contrib.sourceforge.net/tasks/tasks/index.html
Download from here:
http://sourceforge.net/projects/ant-contrib/files/ant-contrib/
Installation instructions from here:
http://ant-contrib.sourceforge.net/


But I'll describe my installation steps here.

OK.  Here is the reward for reading this far!  The download page provides a zip with everything but the jar file.  It took some time to dig our the real download URL that you want.
http://sourceforge.net/projects/ant-contrib/files/ant-contrib/ant-contrib-0.3/
On this page get the bin file ant-contrib-0.3-bin.zip

Unpack the file:

~/Downloads$ ls -l ant-contrib-0.3-bin.zip
-rw-r--r--@ 1 yourRoot  staff    97K 28 Feb 11:00 ant-contrib-0.3-bin.zip
~/Downloads$ mkdir AntContrib
~/Downloads$ mv ant-contrib-0.3-bin.zip AntContrib/
~/Downloads$ cd AntContrib/
~/Downloads/AntContrib$ unzip ant-contrib-0.3-bin.zip


To see the local copy of the API documentation run this:
~/Downloads/AntContrib$ open docs/api/index.html  



The jar file we want is in the lib directory.  Just need to know where to copy it.  With linux systems  you can run 'which' to locate the ant install directory.
~/Downloads/AntContrib$ which ant
/usr/bin/ant







But do a long directory listing and note the directory is actually a link.  After some more exploration I found the actual location to put the jar.  The target directory is owned by the root user so you may need to run the copy command with super user privileges; sudo



~/Downloads/AntContrib$ sudo cp lib/ant-contrib-0.3.jar /usr/share/ant/lib/
Password:
~/Downloads/AntContrib$

Using the If-Then-Else

Now we are ready to use the module.   From the installation notes there is an important first step. In each build file you need to include this:
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>


Here is a sample file that illustrates the if-then-else

<project name="Try If">
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
<if>
 <equals arg1="${foo}" arg2="bar" />
 <then>
   <echo message="The value of property foo is 'bar'" />
 </then>
 <elseif>
  <equals arg1="${foo}" arg2="foo" />
  <then>
   <echo message="The value of property foo is 'foo'" />
  </then>
 </elseif>
 <else>
   <echo message="The value of property foo is not 'foo' or 'bar'" />
 </else>
</if>
</project>


Save the above into a file and call it testif.xml. Invoke ant without a define and with the foo property defined. See the results

~/Documents/salesforce/dev$ ant -f testif.xml
Buildfile: /Users/yourRoot/Documents/salesforce/dev/testif.xml
     [echo] The value of property foo is not bar
     [echo] The value of property foo is not 'foo' or 'bar'

BUILD SUCCESSFUL
Total time: 0 seconds
~/Documents/salesforce/dev$ ant -f testif.xml -Dfoo=bar
Buildfile: /Users/yourRoot/Documents/salesforce/dev/testif.xml
     [echo] The value of property foo is bar
     [echo] The value of property foo is 'bar'

BUILD SUCCESSFUL
Total time: 0 seconds


Using If-Then-Else to Select Test or Prod Properties

Create two build properties files. One for Test and another for Prod.  We will use the if-then-else to select the right one based on the command line.  Put the following into a file called build.xml in your root project directory.


<project name="Salesforce Project"  default="work" basedir="." xmlns:sf="antlib:com.salesforce">
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>

<target name="setup" >
<if>
 <equals arg1="${target}" arg2="test" />
 <then>
   <property file="buildTest.properties"/>
   <property name="system"  value="TEST" />
 </then>
 <elseif>
  <equals arg1="${target}" arg2="prod" />
  <then>
   <property file="buildProd.properties"/>
   <property name="system"  value="PROD" />
  </then>
 </elseif>
 <else>
   <echo message="The value of property target is not 'test' or 'prod'" level="error" />
   <fail/>
 </else>
</if>
</target>

<target name="work"  depends="setup">
   <echo>The ${system} user name is ${sf.username}</echo>
</target>

</project>



Run it with and without the 'target' property

~/Documents/salesforce/dev$ ant -f build.xml
Buildfile: /Users/yourRoot/Documents/salesforce/dev/
build.xml

setup:
     [echo] The value of property target is not 'test' or 'prod'

BUILD FAILED
/Users/
yourRoot/Documents/salesforce/dev/build.xml:20: No message

Total time: 0 seconds
~/Documents/salesforce/dev$ ant -f
build.xml -Dtarget=test
Buildfile: /Users/
yourRoot/Documents/salesforce/dev/build.xml

setup:

work:
     [echo] The TEST user name is myName@myDomain.com.test

BUILD SUCCESSFUL
Total time: 0 seconds



We can now put the real work into the 'work' target and easily switch between Test and Producton




Wednesday, February 20, 2013

Getting Started with Salesforce Ant Migration with Force.com IDE

I've been using the Force.com IDE for years.  As mentioned in previous posts I found that the time to deploy got really long. Then at Dreamforce 2011 I learned to make smaller projects and this really helped.   But recently, I have found deployment time to be excessive (30 to 60 minutes).  Thanks to the folks who post comments on salesforce.stackoverflow.com!  I love the stackoverflow communities.  This post described my experience and one suggestion is to use the Force.com Ant Migration Tool.


As some folks did remark in the post using a command line tool can be a learning curve that we might not have time for.   The following are my steps to use this tool on my Force.com IDE projects.  These steps are mainly about how to adapt the tool to work within the Force.com IDE file structure and to even use and edit it inside the IDE.

Get the Migration Tool

Get the tool via the Salesforce UI under Settings ... Develop ... Tools.  Download the zip file and unpack it.  Open and read the Readme.html.

My system is a Mac 10.6 so I have Java and Ant installed.  Getting these is not hard and the documentation provides the instructions.

Let's assume our IDE workspace is located
~/Documents/salesforce/workspace
. In here are a number of projects. For example, TestMini, TestFull, ProdMini, ProdFull. The Test project are for developing on a sandbox and the Prod project are for Production. The Mini projects hold just the classes, triggers, etc that I need for the current work. The Full projects contain everything. I do not use these for any development. Instead they are a full copy of all the classes, etc that I can use to check into a source control program.


For this discussion I will do everything in
~/Documents/salesforce/workspace/ProdMini  
and call it ProdMini   for short.  All Force.com IDE projects have a subdirectory called "src". In here you will find a package.xml file and subdirectories like classes.  All you really need at this point is the package.xml file. More on this file later.

Setup Ant in the workspace

Copy  ant-salesforce.jar, build.xml, build.properties  to ProdMini. Edit the build.properties and adjust the user name and password (append your token). Next edit the sample build.xml and make these small adjustments. Locate the retrieveUnpackaged section

<target name="retrieveUnpackaged">
<mkdir dir="retrieveUnpackaged"/>
<!-- Retrieve the contents into another directory -->
<sf:retrieve username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" retrieveTarget="retrieveUnpackaged" unpackaged="unpackaged/package.xml"/>
</target>
change
 retrieveTarget="retrieveUnpackaged" unpackaged="unpackaged/package.xml"
to
retrieveTarget="src" unpackaged="src/package.xml"
This sets up the download from Production to your project of anything contained in the package.xml file. Here is what this file looks like:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>OpportunityUtilities</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>OpportunityUpsertTrigger</members>
        <name>ApexTrigger</name>
    </types>
    <version>26.0</version>
</Package>

The version number depends on the version of ant tool and Force.com IDE.  I don't know what happens if these are not in sync.  So update the Force.com IDE and get the latest Migration Tool.

My project has one Apex class and one trigger.  See my early post about opportunities

Download from the server

Ready to download the files from the server.    From the command prompt and after changing directory to get to ProdMini run this:
$ ant -v -lib . retrieveUnpackaged

The -v shows everything that happens. It is optional but helps you understand what is going on.   The "-lib ." says to include the jar file located in this directory.  Then retrieveUnpackaged
tells Ant to run the contents of that section of the ant file.  The result is a download of the contents in the package.  

Deploy a code change

Next make some small change to the class. For example, add a comment.  The new normal with any change like this, for me, is a 30 to 40 minute hurry up and wait when I deploy it to production.  I am going to see what happens now.

Also make one more edit in the build.xml file.  Locate the deployUnpackaged section
<target name="deployUnpackaged">
      <sf:deploy username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" deployRoot="src"/>
    </target>


Notice that I have changed deployRoot to src
 
Now run the ant tool but this time with the deployUnpackaged target  ant -v -lib . deployUnpackaged

It runs a lot quicker that using the Force.com IDE.   This strongly suggests there is a problem with the IDE.

By using the -v flag I get to see all the tests that run. Interesting information.  The deploy might be faster without this flag.

Next: how to use the Ant tool from within Force.com IDE

Return to the Force.com IDE and selection the Production project. Right click and refresh.  Notice the build.xml etc files are listed (if you have no filters).  Click on the external tools button in the top.
  1. First select the build.xml file.  
  2. Then select the External Tools Configurations...  


  1. Select Ant Build and 
  2. Then press the New button







 
  1. Rename the configuration to Retrieve.  
  2. Select the Targets tab and 
    1. unselect the default and 
    2. select retrieveUnpacked (same as we did above on the command line).  
  3. Press Run to save. (this will fail ...)



Yes, the above fails because the ant-salesforce.jar is not on the classpath.
The Force.com IDE console will suggest where you can place the ant-salesforce.jar file. Or fiddle with the Classpath tab in the external tool configuration.








Repeat the above and create a second external tool configuration. This time name it deploy and select the deployUnpackaged target.