Managed packages in Salesforce are essentially apps within Salesforce that can be distributed across organizations. A managed package can be upgraded and the org that installs the managed package does not have any visibility into the code used to create the managed package. Managed packages give you a lot of options as far as adding and distributing functionality. Like most any feature, there can be little quirks that can make something that is typically very simple, a pain to deal with. This blog post will outline an issue I was having and how I was able to work around it.
The issue I was having with using a managed package with Salesforce came when I was trying to use custom components and VisualForce pages with my own controllers to work in conjunction with the managed package. My custom code had to sit inside of pages built within the managed package. When my custom components and pages were loaded, everything seemed to work great. The issue came when I would try to run any action method on my controller to do any sort of action or save state. Salesforce would look for my controller in the namespace of the managed package. Since the controller didn’t exist in the managed package, I would get a null exception saying that it couldn’t find that action method. This error made sense as it was looking in the wrong spot so of course the action method!
I learned that there were a few support tickets open with Salesforce about this same issue. So far there has not yet been a fix that Salesforce has supplied. I had to get this to work one way or another as a big project was on the line to be completed waiting on this custom functionality to be in place. Time to be resourceful.
I knew that using VF remoting wasn’t going to work due to the same namespace issue so pretty much the only other option would be to use the AJAX toolkit. I essentially setup the initial load of the page using the controller since it works fine on page load and then any other operations that would have otherwise been completed using action methods on the controller, I used AJAX. This seemed to be a great option and I was able to get most of my pages to work correctly using this method until…
A common practice with Salesforce for enhancing security is to not allow a user to view or edit data on an object but then using wrapper classes on a controller to wrap your own security around the data that the user can see and edit on that object. By using the wrapper class, the user isn’t technically looking at the sObject data, they are looking at whatever wrapper class you created. Then when the user updates the data from that wrapper class you simply map that data back to the sObject before update. We have done this many times on a variety of objects. One example would be an online store’s order object. We wanted to have fine grain control over what each user could see in that object. An object that Salesforce does this with is the User object for updating.
So what happens when we are back to using our controller inside of the managed package and we need to use wrapper classes? We no longer can access the controller to update data. There is also no way with AJAX to update a record that a user does not have access to. The solution I came up with was to not use a wrapper class but to use a wrapper sObject or a staging sObject. I’m sure you are wondering what I mean by wrapper/staging sObject. Well, this object mirrors the fields that you want to give the user the ability to update. You give the user permissions to create new records in this object and when a record is inserted you can hop into the trigger for the object. Now you are in Apex, getting there from the managed package and you can do all the necessary processing of that record. After you are done processing you can update the original record that you needed to deal with in the first place. As a tip, I used UserInfo.getUserId() to get the current running user to make sure that they had all the necessary permissions to do any operation that I was performing in the trigger. The only thing left is to create a scheduled Apex job to go through and clean up the staging object’s records every so often as the records are a use once and done type of situation.
So there you have it, a few different ways to get around bugs to perform necessary actions in Salesforce. If you have had any issues with something similar feel free to leave a comment below!