I recently needed to make an SObject field transient in a series of Apex wrapper objects used in a controller for a sequence of Visualforce wizard pages. Why is a whole other story.
Here is a simplified example of one of the wrappers:
public class ActionWrapper {
public Action__c sob { get; private set; }
public ActionWrapper(Action__c sob) {
this.sob = sob;
}
// ...
}
Given the large amount of code that depended on these objects I wanted to hide the fact that the SObject field would be null each time a wizard page was posted and so tried code of this pattern (though with the SOQL done in bulk not in each get):
public class ActionWrapper {
public transient Action__c sob {
get {
if (sob == null && sobId != null) {
sob = [select ... from Action__c where Id = :sobId];
}
return sob;
}
private set {
sob = value;
sobId = sob.Id;
}
}
private Id sobId;
public ActionWrapper(Action__c sob) {
this.sob = sob;
}
// ...
}
But this yields the error “Methods cannot be marked transient”: it looks like compilation of get or set without a body is handled differently from get or set with a body. Pretty discouraging…
The good news is that the following pattern solves the problem by separating the transient declaration from the get and set methods:
public class ActionWrapper {
public Action__c sob {
get {
if (sobValue == null && sobId != null) {
sobValue = [select ... from Action__c where Id = :sobId];
}
return sobValue;
}
private set {
sobValue = value;
sobId = sobValue.Id;
}
}
private Id sobId;
private transient Action__c sobValue;
public ActionWrapper(Action__c sob) {
this.sob = sob;
}
// ...
}
Applied this same pattern just the other day, seems silly to have the discrepancy between the “types” of getters and setters.