GraphViz diagrams from Visualforce

The Google Chart API returns a dynamically generated chart image in response to a GET or POST request and articles like Integrating Visualforce and Google Charts provide examples of how to use the API from Force.com. I had a need to represent a graph of relationships and noticed that GraphViz is available (but marked as experimental) through the API. GraphViz is used by SchemaSpy to automatically layout the diagrams of the relationships between objects – see SchemaSpy Org ERD for an example for a Force.com org.

Here is an example of the result of using this API to represent a set of pages and the links between them:

The code to create this output is very simple as the code fragment below illustrates. All you have to do is concatenate together the string that you have worked out using the documentation and the Live Chart Playground. But beware of the 2k length limitation of the resulting encoded URL when using the normal GET. This severely limits how many elements the diagram can include (to about 30 pages for my example even after tweaking to minimize the length). I could not find a way staying solely in Force.com to move to using a POST where the length limit is 16k.

private String createUrl(QuestionPage__c[] qps, AnswerOption__c[] aos) {
    // See http://code.google.com/apis/chart/docs/making_charts.html
    String url = 'http://chart.apis.google.com/chart'
            + '?cht=gv&chl=digraph{[bgcolor=gray97]node[shape=note,style=filled,fillcolor=lightblue,fontsize=9]';
    // Translate ids into indexes - shorter
    Map<Id, Integer> m = new Map<Id, Integer>();
    Integer i = 0;
    for (QuestionPage__c qp : qps) {
        m.put(qp.Id, i);
        i++;
    }
    // Ensure all the pages, whether related or not are shown; just use name as title field is much longer
    for (QuestionPage__c qp : qps) {
        url += m.get(qp.Id) + '[label="' + qp.Name + '"]';
    }
    // Show page to page links - solid lines
    for (QuestionPage__c qp : qps) {
        if (qp.NextPage__c != null) {
            url += m.get(qp.Id) + '->' + m.get(qp.NextPage__c) + ';';
        }
    }
    // Show links via answer options - dashed lines
    url += 'edge[style=dashed]';
    for (AnswerOption__c ao : aos) { 
        if (ao.Question__r.QuestionPage__r.Id != null && ao.NextPage__c != null) {
            url += m.get(ao.Question__r.QuestionPage__r.Id) + '->' + m.get(ao.NextPage__c) + ';';
        }
    }
    url += '}';
    return url;
}

The Visualforce to display the image is simply <apex:image url=”{!url}” />.

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.

SOQL and Apex patterns for multiple related objects

Business logic for one object often requires fields in related objects to be accessed. Suppose you have a number of objects related like this:

(In reality each object would have a number of fields that need to be accessed; in the examples below only the “Name” field is being accessed. Also see the earlier posting A SOQL relationship query example for an introductory example and some important links.)

With a Java background, your first thought on how to write the data loading part of such business logic code might be something like this where each object is lazy loaded as required through a getter method:

public class ClaimLogic {
    private Id claimId;
    private Group__c group;
    private Policy__c policy;
    private Claim__c claim;
    private List<Benefit__c> benefits;
    private List<Relationship__c> relationships;
    private List<Contact> contacts;
    public ClaimLogic(Id claimId) {
        this.claimId = claimId;
    }
    private Claim__c getClaim() {
        if (claim == null) {
            claim = [select Name from Claim__c where Id = :claimId];
        }
        return claim;
    }
    private Policy__c getPolicy() {
    	if (policy == null) {
            policy = [select Name from Policy__c where Id = :getClaim().Policy__c];
    	}
    	return policy;
    }
    // 4 other lazy-loading methods
}

But the pattern I suggest considering instead loads all the data at once:

public class ClaimLogic {
    private Group__c group;
    private Policy__c policy;
    private List<Benefit__c> benefits;
    private List<Relationship__c> relationships;
    private List<Contact> contacts;
    public ClaimLogic(Id claimId) {
        claim = [
            select
                    Policy__r.Group__r.Name,                // Grand parent field
                    Policy__r.Name,                         // Parent field
                    Name,                                   // Field
                    (
                            select
                                    Name                    // Child field
                            from Benefits__r
                            where Name like 'A%'            // Child field filtering
                    ),
                    (
                            select
                                    Name,                   // Association object field
                                    Contact__r.Name         // Many to many associated object field
                            from Relationships__r
                            where Contact__r.Name like 'X%' // Many to many associated object field filtering
                    )
            from Claim__c
            where Id = :claimId
            ];
        group = claim.Policy__r.Group__r;
        policy = claim.Policy__r;
        benefits = claim.Benefits__r;
        relationships = claim.Relationships__r;
        contacts = new List<Relationship__c>();
        for (Relationship__c relationship : claim.Relationships__r) {
            contacts.add(relationship.Contact__r);
        }
    }
}

The advantages of this approach are:

  • Instead of six SOQL queries being executed only one SOQL query is executed. Each query takes a few milliseconds and more importantly there is a governor limit on how many in total can be executed per request so six times fewer is a good thing for both performance and avoiding hitting the brick-wall of the governor limit.
  • While not taken advantage of in the above code, by querying all the objects in one go, the relationship fields (the fields ending in “__r”) in both directions are populated. This allows the whole object graph to be passed around and the various parts of the graph accessed as needed in various methods.

It is when writing this kind of SOQL that clear naming of the relationships (done when the relationships are created) becomes important. The parent relationship name is always taken from the parent object name. The child relationship name can be edited when the relationship is created and it is worth taking care with this to make it clear (and plural). The diagram at the beginning of this post shows the relationship names used in the SOQL in bold.

A few more comments on the SOQL:

  • As well as parent objects, grand-parent objects (and presumably great grand-parent objects – not sure if there is a limit) can be accessed.
  • On child objects, only the immediate children of the object in the root query can be accessed i.e. the grand-children cannot be accessed. So it is important to think about which object to use in the root query; sometimes moving up or down a level results in a solution. The relationship between the root query object and the child object is implicit which takes a bit of getting used to if you have a SQL background. The brackets around the child query are required and it can sometimes take a few goes to get those and the relationship name right.
  • The ability to query objects that are in a many to many relationship with the root object via an association object is a nice surprise.
  • Fields referenced via parent relationships can be used in “where” and “order by” clauses too.

Customizing the Task “Subject Combo” List

Where an organization wants to manually create tasks that have standard subjects, the “Subject Combo (New Window)” button to the right of the subject field in the new task UI is the obvious mechanism to use. The first time I searched for how to customize that list I failed to find the solution, but looking again today I did find it.

A clue is in the help:

Combobox Field Type
A combobox is a picklist that also allows users to type a value that is not already specified in the list.

The task subject field is modeled as a picklist field but presented as an editable text field and the picklist values are presented in a pop-up window that sets the selected value back in the task subject field when an entry is clicked. So to customize the task subjects you just need to customize the picklist values via Setup -> Customize -> Activities -> Task Fields.

Here is an example of the result:

While this Combobox Field Type isn’t conveniently available in Visualforce, it does look like the pattern could be copied by using apex:inputText rather than apex:inputField and with the values for the combobox window obtained in a custom controller from the DescribeFieldResult.getPicklistValues method.

Wanted: the ability to create an instance of an Apex class from the class name

Suppose you have a managed package that has an Apex class called PackageController and a Visualforce page called PackagePage. But for a particular customer the behavior of the class needs to be modified. Now this could be done using public custom setting switches (that can be set in the customer’s org that the managed package is deployed in) but that would mean that the new behavior has to be added to the managed package. Where there are many or arbitrary behavior variations this isn’t a viable approach.

One solution is to copy the source code of PackageController and PackagePage into the customer’s org and modify it for each customer. But then you no longer have an upgradeable package or any intellectual property protection or indeed a product any more.

The approach I am looking to use instead is the strategy pattern. This allows parts of the PackageController’s behavior to be plugged in. The PackageController defines one or more global interfaces and uses a factory to create instances of concrete classes that implement those interfaces and then uses those instances. That factory takes the names of the concrete classes from public custom settings and these are defaulted to the names of the standard implementation concrete classes contained in the managed package. The code would look something like this:

// Example of an interface that abstracts a piece of behavior
global interface InterestStrategy {
    Decimal calculate(Decimal price, Decimal rate, Integer days);
}
// Example of a factory method
public class Factory {
    public InterestStrategy createInterestStrategy() {
        // This creates an instance of the class named by its argument by invoking that class's no-arg constructor
        return (InterestStrategy) System.newInstance(Strategies__c.InterestStrategyClassName__c);
    }
}
// Example of a controller using a strategy
public with sharing class PackageController {
    public void calculate() {
        ...
        Decimal result = new Factory().createInterestStrategy().calculate(price, rate, days);
        ...
    }
}

Given this approach, alternate concrete class implementations of the strategy interfaces can be written in the customer’s org and configured to be used by the PackageController by setting their names in the public custom settings. This way, the new behavior goes where it should go, in the org that is using the managed package not in the managed package itself. The managed package follows the open/closed principle – it is open for extension without needing to be modified to achieve the extension.

Apex already has all the necessary mechanisms e.g. interfaces except one: the ability to create an instance of a class starting from the class name. In the above code this is represented by the non-existent method System.newInstance. The equivalent mechanism in Java is Class.forName(“ClassName”).newInstance().

I’m posting this because the lack of this feature is really hurting our ability to deliver what our customers need. I (and others) have posted the need on the IdeaExchange e.g. Allow Apex code customization of a managed package but there is no commitment from salesforce to deliver this. If you have a managed package or are thinking of creating one, I suggest that you too should push for this feature to be delivered.

PS Type.newInstance was delivered in Summer ’12; see the current Force.com documentation for more detail.