function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Mickey Stringer 5Mickey Stringer 5 

Method Does Not Exist When Calling Static Method

I know there are many threads posted aboubt this compile error, but none seem to offer a solution to what I'm experiencing. The method is static, I've checked for typos, I think I'm passing the right argument...

Background: I'm trying to refactor our org's triggers to revolve around a simple trigger framework. As such, I now need to rip out the logic from the triggers and put them into their own classes. Starting small, I'm working on a trigger that updates the name of a custom object.

The framework I'm using is here: http://chrisaldridge.com/triggers/lightweight-apex-trigger-framework/

The trigger handler class is:
public class PersonTriggerHandler implements TriggerHandlerInterface {

    public Boolean IsDisabled() {
        return false;
    }
 
    public void BeforeInsert(List<SObject> newItems) {
    
        PersonNameUpdate.beforeInsert(newItems);
    
    }
 
    public void BeforeUpdate(Map<Id, SObject> newItems, Map<Id, SObject> oldItems) {
    
        PersonNameUpdate.beforeUpdate(newItems, oldItems);
    
    }
 
    public void BeforeDelete(Map<Id, SObject> oldItems) {}
 
    public void AfterInsert(Map<Id, SObject> newItems) {}
 
    public void AfterUpdate(Map<Id, SObject> newItems, Map<Id, SObject> oldItems) {}
 
    public void AfterDelete(Map<Id, SObject> oldItems) {}
 
    public void AfterUndelete(Map<Id, SObject> oldItems) {}

}

And the PersonNameUpdate class:
public class PersonNameUpdate {

    public static void beforeInsert(List<Person__c> insertList) {
        for (Person__c pers : insertList) {
            pers.Name = (pers.First_Name__c +' '+pers.Last_Name__c);
        }
    }
    
    public static void beforeUpdate(Map<Id, Person__c> newMap, Map<Id, Person__c> oldMap) {
        
        for(Person__c pers : [SELECT Id, Name, First_Name__c, Last_Name__c FROM Person__c WHERE Id IN: newMap.keySet()]){
            
            boolean firstNameChanged = (pers.First_Name__c != oldMap.get(pers.Id).First_Name__c);
            boolean lastNameChanged = (pers.Last_Name__c != oldMap.get(pers.Id).Last_Name__c);
            
            if(firstNameChanged || lastNameChanged) {
            pers.Name = (pers.First_Name__c +' '+pers.Last_Name__c);
            }
            
        }
        
    }

}

I receive the error when I add PersonNameUpdate.beforeUpdate(newItems, oldItems); to the handler class. The full error is
"Error: Compile Error: Method does not exist or incorrect signature: void beforeUpdate(Map<Id,SObject>, Map<Id,SObject>) from the type PersonNameUpdate"

This made me wonder if passing a generic SObject argument to a method that accepts a Person__c Map was invalid, but it works fine in the BeforeInsert method... I'm lost.
Best Answer chosen by Mickey Stringer 5
Narender Singh(Nads)Narender Singh(Nads)
Hi Mickey,

Can you please try this code for me:
public static void beforeUpdate(Map<Id, sObject> newMap, Map<Id, sObject> oldMap) {
        
        for(Person__c pers : [SELECT Id, Name, First_Name__c, Last_Name__c FROM Person__c WHERE Id IN: newMap.keySet()]){
            
            boolean firstNameChanged = (pers.First_Name__c != ((person__c)oldMap.get(pers.Id)).First_Name__c);
            boolean lastNameChanged = (pers.Last_Name__c != ((person__c)oldMap.get(pers.Id)).Last_Name__c);
            
            if(firstNameChanged || lastNameChanged) {
            pers.Name = (pers.First_Name__c +' '+pers.Last_Name__c);
            }
            
        }
        
    }

Let me know what error it throws(If any)
Thanks!

All Answers

Narender Singh(Nads)Narender Singh(Nads)
Hi Mickey,

Have you tried changing the function call as:
public void BeforeUpdate(Map<Id, Person__c> newItems, Map<Id, Person> oldItems) {
    
        PersonNameUpdate.beforeUpdate(newItems, oldItems);
    
    }

This will get rid of the error.

Let me know if it helps.
Thanks!
devedeve
Hi Mickey,

This is because you are using SObject for Map in PersonTriggerHandler class and Person__c in PersonNameUpdate class. Please try this

public class PersonNameUpdate {

    public static void beforeInsert(List<Person__c> insertList) {
        for (Person__c pers : insertList) {
            pers.Name = (pers.First_Name__c +' '+pers.Last_Name__c);
        }
    }
    
    public static void beforeUpdate(Map<Id, SObject> newMap, Map<Id, SObject> oldMap) {
        
        for((Person__c)SObject pers : [SELECT Id, Name, First_Name__c, Last_Name__c FROM Person__c WHERE Id IN: newMap.keySet()]){
            
            boolean firstNameChanged = (pers.First_Name__c != oldMap.get(pers.Id).First_Name__c);
            boolean lastNameChanged = (pers.Last_Name__c != oldMap.get(pers.Id).Last_Name__c);
            
            if(firstNameChanged || lastNameChanged) {
            pers.Name = (pers.First_Name__c +' '+pers.Last_Name__c);
            }
            
        }
        
    }

}
Mickey Stringer 5Mickey Stringer 5
@Narender I can't change to public void BeforeUpdate(Map<Id, Person__c> newItems, Map<Id, Person> oldItems) because the TriggerHandlerInterface class (which the the Person handler implements) writes the method as SObject.

@deve If I do that, I can't reference the Name fields I need in that method. Additionally, PersonTriggerHandler.BeforeInsert passes List<SObject> to PersonNameUpdate.beforeInsert, which accepts the argument List<Person__c>. Why would that work, but not the maps?
Narender Singh(Nads)Narender Singh(Nads)
Hi Mickey,

Can you please try this code for me:
public static void beforeUpdate(Map<Id, sObject> newMap, Map<Id, sObject> oldMap) {
        
        for(Person__c pers : [SELECT Id, Name, First_Name__c, Last_Name__c FROM Person__c WHERE Id IN: newMap.keySet()]){
            
            boolean firstNameChanged = (pers.First_Name__c != ((person__c)oldMap.get(pers.Id)).First_Name__c);
            boolean lastNameChanged = (pers.Last_Name__c != ((person__c)oldMap.get(pers.Id)).Last_Name__c);
            
            if(firstNameChanged || lastNameChanged) {
            pers.Name = (pers.First_Name__c +' '+pers.Last_Name__c);
            }
            
        }
        
    }

Let me know what error it throws(If any)
Thanks!
This was selected as the best answer
Mickey Stringer 5Mickey Stringer 5
Compile Error: Variable does not exist: First_Name__c 
Referencing this location - ((person__c)oldMap.get(pers.Id)).First_Name__c)
Narender Singh(Nads)Narender Singh(Nads)
Hi,
You shouldn't be getting this error.

I tested this code in my org:
public class cls {
    
    void fn(){
    
    		map<ID,sobject> m= new  map<ID,sobject>();
        	account a=[select id,name from account limit 1];
			//account a=new account();
			//a.name='Nads';
			
        	//m.put(a.id,a);
			boolean flag= (a.name!=((RelationTestOBJ__c)m.get(a.id)).Field_1__c);
   }
}

It is giving no error. (Field_1__c is a custom field on RelationTestOBJ__c object in my org.)
 
Mickey Stringer 5Mickey Stringer 5
Sorry, it did actually save. I might have clicked away too early. Thanks!
Unfortunately, now my booleans are not evaluating correctly... They're returning false when they definitely should be true. I've used this type of code before so I'm surprised it's not working. I'll put some more debugging in to see what I can find out, but if you have any thoughts, I'd appreciate them!
Narender Singh(Nads)Narender Singh(Nads)
I can only say once we see the debugging results of your maps
Mickey Stringer 5Mickey Stringer 5

It was only reading the old map. I guess the "pers.First_Name__c" reference wasn't explicit enough to state that I wanted the First name from the new map.

I changed to this and it's working. Do you see any issues or violations of best practices here? (Still new to Apex so can't always look past "working now" to "not going to work when I do a bulk load," or some other scenario :)

public class PersonNameUpdate {

    public static void beforeInsert(List<Person__c> insertList) {
        for (Person__c pers : insertList) {
            pers.Name = (pers.First_Name__c +' '+pers.Last_Name__c);
        }
    }
    
    public static void beforeUpdate(Map<Id, SObject> newMap, Map<Id, SObject> oldMap) {
        
        for(Person__c pers : [SELECT Id, Name, First_Name__c, Last_Name__c FROM Person__c WHERE Id IN: newMap.keySet()]){
            
            Person__c oldPerson = (Person__c)oldMap.get(pers.Id);
            Person__c updPerson = (Person__c)newMap.get(pers.Id);
            
            boolean firstNameChanged = (oldPerson.First_Name__c != updPerson.First_Name__c);
            boolean lastNameChanged = (oldPerson.Last_Name__c != updPerson.Last_Name__c);
            
            System.debug('First Name Changed: ' + firstNameChanged);
            System.debug('Old First Name: ' + ((Person__c)oldMap.get(pers.Id)).First_Name__c);
            System.debug('New First name: ' + pers.First_Name__c);
            System.debug('Last Name Changed: ' + lastNameChanged);
            
            if(firstNameChanged || lastNameChanged) {
            updPerson.Name = (updPerson.First_Name__c +' '+updPerson.Last_Name__c);
            }
            
        }
        
    }

}

Thanks again for your help!
Narender Singh(Nads)Narender Singh(Nads)
Perfect mate!
Narender Singh(Nads)Narender Singh(Nads)
Mickey,
Close this post by marking the best answer. It was indeed a good post.
Mickey Stringer 5Mickey Stringer 5
Already marked! Thanks again man!
Narender Singh(Nads)Narender Singh(Nads)
Happy to help. :D