Apr 25, 2015

Generically Calling External Classes from Managed Packages

Let’s say that you’re building a managed package but one of the target orgs for the package needs some custom logic to execute in the middle of your package logic or perhaps fork into completely different path that is not common to the rest of the orgs that install your package. Let’s say that you have two or three of these “special” orgs that are a minority of the package installs but important enough to handle. Here’s one way to handle such craziness...

The goal of this exercise is to be able to have the target org tell your package that there is some custom code that needs to be executed. We need a way to do this dynamically, and have it controlled by the target org. That feat can be achieve with a custom setting, an interface class, and dynamic class instantiation.

First, you’ll need to create a non-protected custom setting in your managed package. The custom setting is pretty simple, and contains the following text fields:
  • Name - the standard Name field is used to get the values if a specific forking may be needed at specific times.
  • ClassName__c - used to hold the name of the external class that needs to be called.
  • Namespace__c - used to hold a namespace in case the external class is located in a different extension package.

Now that we have a way for the target org administrator to alert the package code that an external class needs to be called, we need to handle that in the package code itself. We’ll first Create Interface class and a method that is so generic, that it can be used with any number of parameters and can get a response that includes any response type. We do that by setting the return variable and the class parameter to the object data type, which can be casted to any type of other data type. That will allow different implementations to use this class in completely different ways.
Now that the interface class is ready, it can be used in strategic locations around the code to call external classes as needed. If you need some added flexibility and have no fear, you can also blindly execute anything you can find in the custom setting. That can be done by instantiating an instance of the external class by dynamically instantiating the interface class, which provides a concrete type that can be instantiated. Note that you’ll need to make sure that you use the namespace in the forName method if you are pointing to a class in an external package.
The code is now done and a new release of the managed package can be created. The only thing left to do is to use the new code from outside the package. You do that by creating a class in the target org or an extension package that implements the base package interface. Parameters that are sent into this class go by the normal apex rules, so maps and lists that are passed can be manipulated in the external class (passed by reference). Since the interface blueprint is flexible, the implementation can be static in case a callout needs to happen (needs to be static in some cases because a trigger starts the execution).

Apr 2, 2015

Salesforce1 Mobile - Fun with IFrames & Matching the Styling

When you start developing for mobile, you tend to find reasons for harnessing the device features that they come with (camera, location services).  If you've ever had the need to snap a photo from Salesforce1 and attach it to a record(in a custom VisualForce page of course), you may have come across the wonderful tag <apex:InputFile />.  It's a definite time-saver versus having to handle the complexities of file formats, sizes, viewstate, governor limits etc.

My guess is that you've also ran into issues when trying to rerender a part of this visualforce page, or perform an "oncomplete" action.  You would get this error if so:

apex:inputFile can not be used in conjunction with an action component, apex:commandButton or apex:commandLink that specifies a rerender or oncomplete attribute

This means that any other part of the page that attempts one of these actions will not be able to do so, simply because the page contains an InputFile tag elsewhere.  I quickly found this solution (using an ActionRegion tag to wrap other parts of the page) that worked initially but as my page grew, the InputFile component broke. The component stopped firing the setter for my Attachment property.  The more I worked with trial and error, I decided to cut my losses and encapsulate it within an iframe so that I could code with freedom on the main page.

It figures that I would find other solutions AFTER taking my plunge into this solution, but it was fun, and I can use this in other ways :)!  Here are other options to using Apex:InputFile tags in more complex situations: https://developer.salesforce.com/forums/ForumsMain?id=906F0000000Acd6IAC

A solution to divide the pages:

  1. Attachment page: Create a page that takes an ID as a url parameter for the ParentId, to be used to insert the attachment. In this page you have the InputFile tag which handles the file. 
  2. Parent page: Show the attachment page in an IFrame. Use javascript functions that can be fired between the child and the parent windows for a seamless user experience however you see fit. (same domain).

Link: Demo

  1. This works in all browsers.
  2. The demo site was built for Salesforce1 and is a great example of using Bootstrap SF1 Theme along with the standard Bootstrap Javsascript library (matching the version to 3.0.1).
  3. The demo is responsive and works in the Salesforce1 app on mobile devices, desktop, and Salesforce1 through the browser.
  4. Other improvements would be
    1. Implement swipe for the Details and Attachments tabs, and convert to "tap" instead of "onclick" events. 
    2. Best Practice: Use JS remoting and remove the view state for better mobile performance.  Implementing remoting on the parent page could be done with this iframe solution being handy.

Link: GitHub

Keys to the solution:

AccountDetail page
  • Contains an IFrame with id = "attachmentIFrame"
  • Contains the submit button as part of the modal. It fires a javascript function from within the iframe to insert the attachment.
  • Contains a close button which is unlimited and able to call an actionFunction which does contain an oncomplete rule (which navigates the user to the attachments tab list).

AttachmentUpload page
  • Contains the Apex:InputFile tag, and has an accessible javascript/actionFunction called "processAttachment". This is the function that the parent page will call.

AttachmentUpload class
  • Contains page accessible method "ProcessAttachment" which will take the attachment property and perform the DML insert.

Salesforce1 & other Goodies:

  • Salesforce1 navigation vs desktop navigation are different, see this JS function than helps to handle this (used here when clicking on a link to the attachment).

  • When the user clicks the Close button after they uploaded the attachment(s), we are able to show the Bootstrap tab very easily.

By separating the inputFile tag, you can use rerender or oncomplete attributes on the parentpage again, without the need for actionRegion tags or multiple Form tags.

Styling is done with the BootstrapSF1 package and the Bootstrap Javascript library to match. This will work in Salesforce1.