I'm writing some new code, and I came across a curious situation. We are using a dynamic piece of code that determines how a record should be handled based on its ID value (e.g. different objects have different fields). The code look briefly like this:
public class Mapping {
public SObjectField name, unitprice, quantity, ...;
public static Mapping getMapFor(SObjectType entity) {
// populate a new map based on given values
if(entity == Opportunity.SObjectType) {
name = Opportunity.Name;
unitprice = null;
...
}
if(entity == OpportunityLineItem.SObjectType) {
...
}
}
}
NOTE: The actual code has over a thousand lines of code, caching, etc. Example is illustrative only.
This code works beautifully, since it lets us abstract discrete logic across multiple data types.
As example, we can do:
record.put(m.totalprice, (decimal)record.get(m.unitprice) * (decimal)record.get(m.quantity));
Instead of writing ten versions of the code that do the exact same function with different records.
Next, there's a component that accepts a standard controller as an attribute. This gives us access to cancel()
, save()
, etc that would be available on the actual Visualforce page with very little overhead, and, of course, allows direct access to the record.
Now, here's where the twist comes into play:
public class componentController {
public ApexPages.StandardController controller { get; set; }
// Other data goes here
public void init() { // called via action function on component load,
// since we can't access controller in constructor
// and can't call an action on a component directly.
// The following line fails to compile
Mappng m = Mapping.getMapFor(controller.getId().getSObjectType());
}
}
One would wholly expect this code to function verbatim, because ApexPages.StandardController
getId
logically returns an Id, right? Right? Wrong!. Instead, it returns a String value.
There's no documentation on why it returns a String, since clearly it will always be an ID value (or will it...?). I have at least two easy workarounds (I'm going to use controller.getRecord().Id.getSobjectType()
), but I would like to know why the Powers That Be™ decided that they wanted to return a simple String instead of correctly typing the value as an Id.
Is there something I need to know? Are they planning on changing how this function works? Should I not rely on getId
now or in the future? Could someone fix this so that it works correctly?