Google charts and data privacy

Google provides a great javascript library to create really impressive charts for your web application. I have used it a couple of times and I managed to generate the desired chart in very little time.

However, there is always something to consider when using this library. As stated in the Security and Privacy section: “All charts depend on linked JavaScript libraries, and some might send chart data from the browser to another location for preprocessing.” This might be a show stopper for many clients, since data may be sent to external locations. If you want to find out more details about what data is sent you need to go to every chart type and read the Data policy. Since I had to do this in order to evaluate the solution for one of our projects I am summarizing this information in the table below

Chart Type Data Policy
Annotation Chart  All code and data are processed and rendered in the browser. No data is sent to any server.
Area Chart All code and data are processed and rendered in the browser. No data is sent to any server.
Bar Chart All code and data are processed and rendered in the browser. No data is sent to any server.
Bubble Chart All code and data are processed and rendered in the browser. No data is sent to any server.
Calendar Chart All code and data are processed and rendered in the browser. No data is sent to any server.
Candlestick Chart All code and data are processed and rendered in the browser. No data is sent to any server.
Column Chart All code and data are processed and rendered in the browser. No data is sent to any server.
Combo Chart All code and data are processed and rendered in the browser. No data is sent to any server.
Diff Charts NO INFO
Gauge All code and data are processed and rendered in the browser. No data is sent to any server.
Geochart Locations are geocoded by Google Maps. Any data that does not require geocoding is not sent to any server.
Histogram All code and data are processed and rendered in the browser. No data is sent to any server.
Intervals NO INFO
Line Chart All code and data are processed and rendered in the browser. No data is sent to any server.
Map Map are displayed by Google Maps. Please refer to the Google Maps Terms of Service for more information on data policy.
Organizational Chart All code and data are processed and rendered in the browser. No data is sent to any server.
Pie Chart All code and data are processed and rendered in the browser. No data is sent to any server.
Sankey Diagram All code and data are processed and rendered in the browser. No data is sent to any server.
Scatter Chart All code and data are processed and rendered in the browser. No data is sent to any server.
Stepped Area Chart All code and data are processed and rendered in the browser. No data is sent to any server.
Table All code and data are processed and rendered in the browser. No data is sent to any server.
Timeline All code and data are processed and rendered in the browser. No data is sent to any server.
Treemap All code and data are processed and rendered in the browser. No data is sent to any server.
Trendlines NO INFO

So most  of the chartss don’t really send the data to a 3rd party to render. There’s information missing for a couple of types probably because they were still in beta at the time of the evaluation.

Information was updated on 2014.02.12

Posted in Data security, Development, Javascript | Tagged , , | Leave a comment

Redirecting from Salesforce Visualforce pages (Internet Explorer friendly)

A quite common requirement is to click a button and redirect users to different urls based on some business logic. Lets focus on the more complex scenario where a controller is required to determine the target url.

Apparently you need a button setting the Content Source to be a Visualforce page. The interesting point is how to handle the redirection. Assuming you use a String variable in your controller (i.e. strRedirectUrl) you can do this with Javascript using the following code

<apex:page Controller="MyRedirectController">
    <script type="text/javascript">
    if (!{!hasErrors})
    {
        window.top.location = "{!strRedirectUrl}"; 
    } 
    </script>
</apex>

Then the only thing you need to do in the Controller code is to set the proper value for strRedirectUrl.

Looks ok, works most of the times, BUT we have identified strange behaviour in one Salesforce Org.

When using Internet Explorer (IE 9, IE10) the popup window either turns blue and doesn’t redirect (yes we managed to make the Blue screen of death appear in Salesforce !!) or it closes automatically. Even more it worked fine when the URL was a salesforce url.

Any hints why this may happen are more than welcome…

So we needed an alternative approach which is the following

Use the action attribute of the <apex:page> component ! 

The code is also very simple

<apex:page Controller="MyRedirectController" action="{!doRedirect}">
    <apex:messages />
</apex:page>

The only thing you need to do is add a doRedirect method in your apex controller class which either redirects to the target url or returns null in case of an error (consider displaying an error message to inform the user.)

Posted in apex, Browser, Development, Firefox, IE, Javascript, Visualforce | Tagged , , , , , , , | 1 Comment

Emails sent from Salesforce via Apex are not delivered when using Email Relay

This week he had an issue with emails sent from Salesforce. In more details we have implemented a Visualforce page allowing the user to select recipients and send them all an email with some information related to a specific Salesforce record.

This has been implemented with Apex outbound email functionality offered by the platform. I will not go into more details regarding the implementation, since its a very complex one and not of interest for this specific post. The only interesting thing to mention regarding the setup is that there was an email relay server involved.

Problem: Suddenly in one of the Sandboxes, emails were not delivered !

Lets see…

  • Limits ? Maybe the daily limits for emails sent have been hit. How to check ? with debug logs… Nothing there, emails were sent successfully.
  • Now what? Checking the email logs sounds like a good idea ! You can request an Email log via the Setup menu under Monitor -> LogsEmailLogFiles

After downloading the csv file, I realised that the message “[internal] no MXs for this domain could be reached at this time” was reported for most rows (all the outbound ones)

What does this mean ? According to salesforce help (http://help.salesforce.com/HTViewSolution?id=000180767&language=en_US) it was related to the email relay server. That was indeed the problem !

Why does this story worth a post ? Because it’s one of these silent failures which don’t announce themselves and they are not straight forward to trace.

Posted in apex, Development | Tagged , | 1 Comment

Lookups, Activities and Performance

I guess you all know it’s not possible to create a lookup field on an Activity… What do you do when you really need a lookup ?

The easiest way to go is create a Text field for the related object Id and handle the relationship with triggers/Visualforce pages. You may even create a formula field in order to add in on Page layouts and display a link.

BUT…

Text fields are not indexed by default, so you may (will) encounter performance issues and Non-Selective query Exceptions !

SO DON’T FORGET to set the Text field as External Id. 

This way Salesforce will create an Index for this field and save you from trouble

Posted in apex, Development, Visualforce | Tagged , , , | 1 Comment

Salesforce URLFOR redirecting to a Visualforce page which is part of a package

This is a quick one but we struggled a little bit before finding out how to make it work.

Requirement: Redirect to a Visualforce page which is part of a package from a Javascript button.

URLFOR($Page.NAMESPACE__MYPAGE) doesn’t even compile…

but the following works like a charm !

URLFOR(“/apex/NAMESPACE__MYPAGE”);

yes it’s 2 _ in between

Posted in Development, Uncategorized, Visualforce | Tagged , , , , | 1 Comment

Salesforce generates “Unknown Exception” during Deployment

Have you ever encountered an “Unknown exception” error message when trying to deploy/validate a Deployment Set ? Something like the following ?

Image

It doesn’t really provide you with a lot of information, so no idea what to do right ?Before contacting Salesforce Support, maybe it worths giving a try to the following:

Go to the Developer Console and Clear the Heap Dumps !

Image

Hope it helps…

P.S. The explanation behind this, is that the Heap Dumps are also generated during deployment and this requires too much memory ;-)

Posted in Deployment, Development, Exceptions | Tagged , , , , | Leave a comment

Using field sets for dynamic validations in Apex

In Salesforce validations are usually done using the standard functionality offered out of the box.
However there are cases when you need to check specific values but when you perform a certain action i.e. click on a button. In our use case we have to verify that a number of fields are NOT empty before proceeding to the next step.

A typical design for a button is a Visualforce Page and a Controller. In this case you would do the validation in the controller code, probably with an IF statement. It works but not very flexible right ?

Well lets try with field sets ! The idea is to define all fields you need to check in a field set and in the code loop and verify they do have a value. Simply, easy to program and very dynamic ! Do you need more fields to be checked ? Add them in the field set…

And the code to do this is just a couple of lines:

List<Schema.FieldSetMember> lMandatoryfields =
Schema.SObjectType.OBJECT.fieldSets.getMap().get(Label.Req_Fields_Field_Set_Name).getFields();
for (FieldSetMember fSetMember:lMandatoryfields)
{
    if (relatedObject.get(fSetMember.getFieldPath()) == null)
    {
        isError=true;
        sMissingFieldNames.add(fSetMember.getLabel());
    }
}
if (isError)
{
    Apexpages.Message m = new Apexpages.Message(Apexpages.Severity.ERROR, 
                                                Label.Req_Field_Missing_Error_Message);
    Apexpages.addMessage(m);
    for (String strMissingFieldName:sMissingFieldNames)
    {
        Apexpages.Message m1 = new Apexpages.Message(Apexpages.Severity.ERROR,
                                                     strMissingFieldName);
        Apexpages.addMessage(m1);
    }
    return;
}

If you want to do a more complex check you can consider using custom settings.

Posted in apex, Uncategorized | Leave a comment