0

My understanding of static methods is that they hold the data until the end of the transaction, right? So, if I wanted to pull information about a set of ids that would be referenced during a for loop, I could put those into a static method, right?

In essence, I have code that does this.

  1. Update parent record
  2. Check if parent record has open opps
  3. Create one if it doesn't have an open opp

I'm having trouble with #2. I thought I could create a static method like this

public static Map<id,Contact> contactOppLookup(set<id> contIDSet){
    //Gets the number of opportunities on the contact id Set and holds those contacts until the end of the transaction
    get{
        if(contIDSet.size()>0){
            contactOppLookup = new Map<id,Contact>([SELECT id, Opportunity_Count__c, Opportunity_Count_Open__c FROM Contact]);
        }
        return contactOppLookup;
    }
    set;
}

And then run that through a simple boolean method:

public static boolean openOppVerify(id contid){
    //Returns TRUE if there is an open opportunity on the contact
    //default result to false
    boolean openOpp = false;

    if(contactOppLookup.containsKey(contid)){
        Contact c = contactOppLookup.get(contid);
        if(c.Opportunity_Count_Open__c>0){openOpp=true;}            
    }

    System.debug('openOppVerify returns ' + openOpp);
    return openOpp;
}

But I can't seem to get it to work. Is it because I am sending (set<id> contIDSet)?

I am getting these errors at the get line of contactOppLookup: Missing ';' at '{' and Variable does not exist: get

  • Suggest you make the method and the property names different. If contactOppLookup is resolving to the method you need contactOppLookup(idSet).contains(...). But you probably don't want to requery on every access so a proprty would potentially be a better approach. – Keith C Aug 29 '18 at 18:50
3

You're mixing up the syntax for declaring a property with getter and setter accessors and implementing a method, which may or may not have a name like getSomeData(). This is easy to do in a Visualforce context because the Visualforce runtime treats these as more or less equivalent.

A key distinction, though, is that property accessors can't take parameters - they are meant to return and/or mutate underlying data. What you've got here

public static Map<id,Contact> contactOppLookup(set<id> contIDSet){
    //Gets the number of opportunities on the contact id Set and holds those contacts until the end of the transaction
    get{
        if(contIDSet.size()>0){
            contactOppLookup = new Map<id,Contact>([SELECT id, Opportunity_Count__c, Opportunity_Count_Open__c FROM Contact]);
        }
        return contactOppLookup;
    }
    set;
}

is a method. You should remove the get {} and set; declarations, because they have no role to play here. Those property accessors are used to implement logic around accessing the properties (instance variables) of a class.

Where properties could come into play in this situation might be, supposing you had a class MyClass with a property that contains a Set of Ids to be queried, to use another property to lazily load and then cache the query results the first time you need them.

 class MyClass {
     public Set<Id> someIds {
         get { 
             return someIds;
         }
         set { 
             someIds = value; // `value` is the automatically supplied parameter
             myContacts = null; // Clear our cache
         }
     }

     public List<Contact> myContacts {
         get {
             if (myContacts == null) {
                  // We haven't run the query yet. Query and cache results.
                  myContacts = runQuery(someIds);
             }
             return myContacts;
         }
         private set;
     }
}

Then, your code that uses this class can safely set someIds and access myContacts as many times as it wants (including in a loop) without risking SOQL limits.

That confusion aside, what you're trying to do makes sense: you have a query you need to run with specific parameters and you want to cache the results of that query so that you can use them efficiently throughout the transaction. That's good - it's a key bulkification and performance issue in Apex. You just need to tweak your approach a little bit to get it right.

It's also possible (not having seen the code that is meant to use this method) that you can achieve your objective without properties at all, simply by performing the query at a single point in the flow of your code and storing the results in an instance or local variable.

It's not clear that static variables are required here; they're used to persist data throughout the scope of a transaction. static methods, by contrast, don't have anything to do with data lifetime as such - they are methods associated with the class itself, rather than with a single instance, and have no access to the class's instance variables and properties for that reason. String.isBlank() is an example.

3

You have got few things wrong here.

Static methods

Static methods are mostly utility methods. They are used when you want to access a method in a class with the class actually being instantiated. You can find more about it on its documentation.

Yes they hold the data during their lifecycle but for only those variable which were defined within the method body. But if you return a value from the method, it does live outside of the method.

Issue

In your scenario, you have issues with your static method contactOppLookup. You are trying to use the automatic property feature which is available on the class or instance level variables and that the return statement should be the last statement in any method. And thus you are getting a compile time error there.

You need to correct the syntax of your method here, which should look something as below:

public static Map<id,Contact> contactOppLookup(set<id> contIDSet){
    .. do all my operations here ..
    if(contIDSet.size()>0){
        contactOppLookup = new Map<id,Contact>([SELECT id, Opportunity_Count__c, Opportunity_Count_Open__c FROM Contact]);
    }

    .. the return statement is the last statement in any method .. 
    return contactOppLookup;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.