Skip navigation

Category Archives: JSON

This one’s for you, coffee-shop hopping Force.com developers who go to make some changes to your code in Eclipse and — blocked! Login must use Security Token! Uggh. But I hate Security Tokens – sure, sure, it makes way more sense to use them. Definitely a best practice. But, well, sometimes I’m lazy. I confess – I very often just use Trusted IP Ranges.

So, for those of you out there that have been in my situation, and like me don’t like entering Security Tokens into your Eclipse, SOQLExplorer, Data Loader, etc., and prefer to just use Trusted IP Ranges and basic username/password, I’m guessing you find yourselves doing this over and over again:

  1. Show up at Coffee Shop you haven’t been to before – or at which you’ve never done any development on a particular Force.com project / org.
  2. Login to Eclipse.
  3. Try to save something.
  4. Fail – you’re at a non-trusted location and you’re not using the Security Token!
  5. Login to Salesforce.com.
  6. Go to your Personal Information.
  7. Copy the IP address from your most recent login.
  8. Go to Network Access, and add a Trusted IP Range, and paste in the IP Address from Step 7 into both Start and End IP Address. Click Save.
  9. Go back to Eclipse and resave.

Wish there was a way to do this faster?

There is – here’s a little convenience script for the uber-lazy, coffee-shop hopping, Security Token-hating Force.com developer – if there are any of you out there other than me, this if for you!

The Idea: a one-click link in a Home Page Component

My idea: create a Home Page Component for the Left Sidebar that, in one-click, adds a new Trusted IP Range corresponding to the current IP you’re at.

Problem 1: there’s no way to get your current IP address from just pure client-side JavaScript. Lots of server languages can give you this, but not client-side JavaScript.

Problem 2: how to quickly create a new Trusted IP Range? There’s no API access to the Trusted IP Range object (which is probably a good thing from a security perspective 🙂

Problem 1 Solution: Use JSONP + an External Site

To make this a reality, I took the advice of StackOverflow and leveraged JSONP, which allows you to send an AJAX request to an external website and have the result returned in JSON format to a pre-designated callback JavaScript function, which immediately gets called. The basic syntax of this is

Problem 2 Solution: URL Redirect with params passed in

One thing I love about the Force.com platform is that almost every action you might want to take, whether for modification of metadata or data, can be initiated by going to a specific URL. To create a new Account record, you go to “/001/e”. To view all users, you go to “/005”. And almost any field on a particular page can be pre-populated by passing a corresponding URL Parameter (although these are not always consistent). And so it is with Trusted IP Ranges – to create a new Trusted IP Range, head to “/05G/e”. And to pre-populate the Start and End IP Address, you simply have to pass in the right query string parameters: “IpStartAddress” and “IpEndAddress”.

All together now! The final product.

So here’s the final solution:

  1. Go to Setup > Home Page Components > Custom Components.
  2. Click New.
  3. Enter a name, e.g. “Add IP to Trusted Ranges”, and select “HTML Area” as the type. Click Next.
  4. For Position, select “Narrow (Left) Column”.
  5. Click the “Show HTML” checkbox on the far right, and enter the following code for the body, then click Save.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script><script type="application/javascript">  function addIPToTrustedRanges(){  jQuery.getJSON( "https://smart-ip.net/geoip-json?callback=?", function(data){ var ip = data.host; window.location.href= "/05G/e?IpStartAddress="+ip+"&IpEndAddress="+ip; } ); } </script><a href="javascript:addIPToTrustedRanges();">Add Trusted IP (using Smart IP)</a>

6. Go to Home Page Layouts, and add this Home Page Component to your layout as a System Admin.

Now return to your home page, and voila! Here’s what you’ve got: a link that, when you click, it takes you to a prepopulated new Trusted IP Range – just click Save, and boom, get back to Eclipse and save your code!

TrustedIPRange_HomePageComponent

PrepopulatedIPAddressRange

How does it work?

Nothing crazy here, but I’ll step through the code anyhow:

  1. Load jQuery from the Google API’s CDN, so that we can use the handy getJSON() method.
  2. Define a global function called  addIPToTrustedRanges – this function performs an AJAX callout to the endpoint  “https://smart-ip.net/geoip-json&#8221;, passing in the name of a callback function to execute with the JSON data that this endpoint returns. So Smart IP basically returns a little string of data that is a JSON-serialized JavaScript object, whose “host” property is your current IP Address (the real one, not some NAT-translated private IP). Then jQuery calls your callback function, which, in the getJSON() method, is defined as an anonymous function in the second parameter — and passes in  this JSON string as an argument to the function. This is all legal, within the confines of the JavaScript same-origin policy, because of JSONP.
  3. In our anonymous callback function, we do a URL redirect, passing in our current IP address as both the Start and End IP Address as parameters to the new Trusted IP Address page:
    "/05G/e?IpStartAddress="+ip+"&IpEndAddress="+ip;
  4. Then we click Save, and we’re done!

In Winter 12, Salesforce very quietly, and without any fanfare, introduced a capability to Apex that has been something of a holy grail to insane Force.com geeks like myself: the beginnings of support for Reflection in Apex. Which intrepid explorer blazed the trail that led to this prodigious capability? For those of you who keeping score, our silent hero’s name is not Indiana, but Jason. Or, more precisely, JSON.

This is a bit of a historical post, meant to pave the way for a more radical post coming later this week (stay tuned!). It describes events / features that have occurred / been introduced over the course of the past year, but whose full significance is only now being discovered by many Force.com developers. Understanding these developments will be a crucial preliminary to reading my upcoming post on an extension of Tony Scott’s trigger pattern to allow for scalable, extensible triggers usable by managed package developers / ISV’s (there, I let the cat out of the bag!)

Ancient History: Native JSON Support lands in Apex

In Winter 12, Salesforce added native support for JSON to Apex, meaning that you can, in just 2 lines of code convert (nearly) any Apex class/object into a JSON-formatted String, and then convert it back from a String into the proper Apex class/object. For instance:


Map<String,String> params = new Map<String,String>{
    'foo' => 'bar',
    'hello' => 'world'
};
// Serialize into a JSON string
String s = JSON.serialize(params);
// --> yields '{"foo":"bar","hello":"world"}

// Deserialize back into an Apex object

// Define the Type of Apex object that we want to deserialize into
System.Type t = Map<String,String>.class;

params = (Map<String,String>) JSON.deserialize(s,t)

The addition of support for JSON saved ISV’s the immense hassle (and extremely-limiting obstacle) of implementing their own JSON serialization classes, which could very quickly consume all of the 200,000 Script Statements Governor Limit. So needless to say, this alone made native JSON support a godsend to Apex developers.

The Tip of the Iceberg: System.Type and Apex Interfaces

But notice that little System.Type class that we instantiated prior to deserialization. As the Apex development team was building in JSON support, they laid the foundation for something even bigger – an Apex way to achieve what’s known as “Reflection”, or dynamic instantiation/execution of classes/methods based on name. For developers looking for a parallel in Force.com, this is similar to creating a new Sobject by getting a Schema.SObjectType token from the Global Describe Map using an arbitrary String (e.g. ‘Account’) as the map search key, and then calling the newSObject() method. In this scenario, you could have received the dynamic key (‘Account’) from anywhere — from a text field in a custom object in your database, from a JavaScript prompt in the client, etc., and run totally dynamic logic (the instantiation of an arbitrary SObject type) based on that String value.

How does this Schema example connect to Trigger Patterns? Well, the reason that the dynamic SObject instantiation from Schema data works is that each Custom and Standard Object in your database is an instance of an interface called “SObject”. An interface is a definition of methods that all implementations of that interface (such as Account, Contact, MyCustomObject__c) must support. This is why can cast any Account, Contact, or custom object record into an SObject and then get access to some of the dynamic methods that the SObject class supports, such as getField(String fieldName) or getSObject() — because each Account, Contact, or CustomObject__c record is not just an instance of an Account, Contact, or CustomObject__c — it’s also an implementation of the SObject interface, which defines the methods getField(), getSObject(), etc.

With native JSON in Apex, you can now take this Reflection business a huge step further, thanks again to the magic of interfaces. Before we tackle custom interfaces, let’s consider an important standard Apex interface: Schedulable. The Schedulable interface looks like this:


global interface Schedulable {
    global void execute(SchedulableContext ctx);
}

The power of Apex classes that implement Schedulable is that they can be scheduled for execution at a later date/time using the System.schedule() method, like so:


// Get an instance of MyScheduledClass,
// which implements Schedulable
Schedulable c = (Schedulable) new MyScheduledClass();

// Schedule MyScheduledClass to be run later
System.schedule('CleanUpBadLeads','0 0 8 10 2 ?',c);

Now, for those of you who were excited about Skoodat Relax, you may have just realized how it all works, and you are absolutely right! One of the features of Relax is its ability to store the name of a Scheduled Apex Class, and the CRON schedule that dictates when it should be run, in a custom Object called Job__c in Salesforce, and then dynamically activate, deactivate, and run the desired classes at the desired times. And the not-so-secret secret (Relax is on GitHub) behind it is: it all works because of interfaces… and because of native JSON support.

Taking this a step further, as Relax does, we can define complex custom interfaces, with whatever methods we’d like, and then, when our Apex code is run, we can call these methods on whatever implementation of our interface we are handed:


// Our interface definition
public interface Runnable {
   public void run();
}
// A sample implementation
public class DestroyBadApples implements Runnable {
   public override void run() {
       delete [select Id from Apple__c where CreatedDate <= :Date.today().addYears(-365)];
   }
}

// A sample use of this interface
public class RunStuff {
   public RunStuff() {
      // Define the stuff we'd like to run
      List<Runnable> stuffToRun = new List<Runnable>();
      stuffToRun.add(new DestroyBadApples());

      // Run the stuff
      for (Runnable r : stuffToRun) r.run();
   }
}

Part 3, in which we catch the scent of our prey: Dynamic Class Instantiation with JSON

With Apex support for interfaces, developers already had, prior to Winter 12, one of the two key tools they needed that would make possible the Apex Holy Grail of dynamic method calls / code execution. The missing tool was the ability to create an implementation of an interface without knowing the class’ name beforehand. In our previous examples, notice how we had to hardcode the name of the implementations, e.g. MyScheduledClass and DestroyBadApples.

With Winter 12, our humble hero JSON gave us that missing tool. How so? Well, the JSON.deserialize(string,type) method allows us to deserialize any String into any supported Apex Type, as defined by Apex Classes which have a corresponding representation as a System.Type, a little-noted System class that crept in with Winter 12. The key tricks that turned System.Type into a Holy Grail as early as Winter 12 were

  1. A little trick involving an empty JSON String, e.g. “{}”
  2. System.Type.forName(name)

Combining these two tricks with interfaces, and voila! We have Dynamic Class Instantiation in Apex:


// A sample use of this interface
public class JobRunner {
   public static void ScheduleJobs() {
      // Retrieve the jobs we'd like to schedule from a custom object
      for (Job__c j : [select JobNumber__c, Cron__c, ApexClass__c from Job__c]) {
          try {
              // Get the Type 'token' for the Class
              System.Type t = System.Type.forName(j.ApexClass__c);
              if (t != null) {
                 // Cast this class in to a schedulable interface
                 // (if the cast fails, we'll get an error)
                 Schedulable s = (Schedulable) JSON.deserialize('{}',t);
                 // Schedule our Schedulable using the stored CRON schedule 
                 System.schedule('JobToRun'+JobNumber__c,Cron__c,s);
              }
          } catch (Exception ex) {}
      }
   }
}

Part the 4th, in which our hero’s achievements are acknowledged but his powers not increased

In Summer 12, Salesforce “officially” acknowledged its intentions with System.Type and added a newInstance() instance method allowing for less hackish dynamic class instantiation by name. However, the JSON method remains far more powerful, as it allows us to dynamically populate all manner of fields/properties on our dynamically-instantiated objects — using industry-standard JSON syntax, allowing this dynamic population to be initiated client-side and completed server-side in Apex! If your mind is not spinning with all of the possibilities right now, I’m sure it either did so already during the past 12 months, or will start doing so very soon, particularly when we talk about applying this capability to Triggers (more propaganda for the next post!)

So where can Salesforce go from here? Well, there is still no direct way to dynamically execute a particular method on an Apex class without hard-coding the method’s name. Support for this would take Reflection in Apex to a whole new level. For now, though, well-crafted Interfaces can usually get around this limitation. The real meat of the work was done early last year when Salesforce R&D was “snowed over” in development for Winter 12, and for the fruit of those 4 months, the Force.com Development community should be immensely thankful.