2

3 Objects --

  • Application
  • Auth Contact
  • AppAuthContact

AppAuthContact is a Junction Object between Application and Auth Contact. The fields in AppAuthCon are ApplId, AuthConId and ContactId.

I have requirement to create a trigger on User record when created.

  1. Find matching Auth Contact for new User using Email
  2. Auth Contact found
  3. Find all AppAuthCon for Auth Contact.
  4. Update all such AppAuthCon records and populate Contact -- contact lookup to be populated using contact of that user
  5. Remove Auth Contact record --deleting

Following is my trigger

   trigger UserTrigger on User (after insert) {
UserTriggerMethod.updateApplicationEditor(trigger.oldMap, trigger.newMap);}

Following is apex class code called from trigger

public with sharing class UserTriggerMethod {
    public static void updateApplicationEditor(Map<ID,User> mapOldUser,Map<ID,User> mapNewUser)
    {   
        if(mapNewUser != null && !mapNewUser.isEmpty())
        {
            for(User user : mapNewUser.values())
            {
                Auth_Contact__c AuthContact = [SELECT Id 
                                                FROM Auth_Contact__c 
                                                WHERE Email__c = : user.Email LIMIT 1];

                if(AuthContact ! = null)
                {
                    List<App_Auth_Contact__c> lstAppAuthCon = [SELECT Contact__c
                                                                FROM App_Auth_Contact__c
                                                                WHERE Auth_Contact__c = : AuthContact.Id];              

                    List<App_Auth_Contact__c> lstAppAuthContoupdate = new List<App_Auth_Contact__c>();
                    List<Auth_Contact__c> lstAuthContacttodelete = new List<Auth_Contact__c>();

                    for(App_Auth_Contact__c AppAuthCon: lstAppAuthCon)
                    {
                        AppAuthCon.Contact__c = user.ContactId;
                        lstAppAuthContoupdate.add(AppAuthCon);
                    }

                    lstAuthContacttodelete.add(AuthContact);

                }
            }
        }
        if(lstAppAuthContoupdate.size() > 0)
        {
            try
            {
                update lstAppAuthContoupdate;
            }
            catch(DMLException e)
            {
                system.debug(e.getMessage());
            }
        }
        if(!lstAuthContacttodelete.IsEmpty())
        {
            delete lstAuthContacttodelete;
        }
    }
}

Issues faced:-

  1. How do i check that delegated contact exist

if(AuthContact ! = null) -- giving error when i save

  • 1
    What is the error message text that you get when trying to save this code? – Mark Pond Sep 27 '13 at 16:55
5

As @sfdcfox noted, your immediate issue was ! = should be !=. However, you have several other issues, ranging from additional compile-time errors to inefficient code to bad practices which really should be addressed.

Here's what I see:

  • You don't need to pass trigger.oldMap to an insert handler; it will always be null (there are no 'old' values for an insert). See Trigger Context Variables in the Apex Programmers guide for more. If you plan to expand this trigger handler for updates, you can add it back for testing if the user's email has changed.
  • You don't need to test mapNewUser for null or empty; the insert trigger won't be called if there are no new User records being inserted. If you expand the trigger handler for updates, you will need to check if oldMap is null.
  • Critical: you are running SOQL queries inside a for loop. This is a quick way to hit the SOQL query limit, and a very bad practice. I recommend reading all of the Apex docs on triggers, but especially Common Bulk Trigger Idioms.
  • You declare lstAppAuthContoupdate and lstAuthContacttodelete inside a block, but try to use them outside the block. This will result in additional compile time errors.
  • You are catching errors in your trigger handler, and then doing nothing but logging them. This might be okay for your use case; just note that these caught-and-suppressed errors will not prevent the new users from being inserted, and the only record of an issue will be in a logfile. If new user creation should be halted for these errors, either remove the error handler (letting the error propagate to the caller), or use [object].addError() in your handler to add errors to affected user objects. If you don't want to halt new user creation, consider emailing the errors to an Administrator.

Here's a reworked version of your code, using only one SOQL query and using maps to avoid the need for more queries. Note that you'll have to update your trigger to only pass trigger.newMap.

public with sharing class UserTriggerMethod {
    public static void updateApplicationEditor(Map<ID,User> mapNewUser) 
    {   

        // get a list of emails for the newly inserted users
        List<String> emails = new List<String>();
        for (User u : mapNewUser.values()) {
            emails.add(u.email);
        }

        //query all auth contacts (and associated App Auth Contacts) at once
        List<Auth_Contact__c> AuthContacts = [ 
            SELECT id, Email__c, 
                       ( SELECT Contact__c from App_Auth_Contacts__r) 
              FROM Auth_Contact__c 
             WHERE Email__c in :emails ];

        //create a lookup from email to AuthContact
        map<string, Auth_Contact__c> emailToAuthContactMap= new map<String, Auth_Contact__c>();
        for(Auth_Contact__c ac : AuthContacts) {
            emailToAuthContactMap.put(ac.Email__c, ac);
        }

        List<App_Auth_Contact__c> lstAppAuthContoupdate;
        List<Auth_Contact__c> lstAuthContacttodelete;
        for(User user : mapNewUser.values()) {

            if(emailToAuthContactMap.containsKey(user.email)) { 

                Auth_Contact__c AuthContact = emailToAuthContactMap.get(user.email);

                List<App_Auth_Contact__c> lstAppAuthCon = AuthContact.App_Auth_Contacts__r;              

                lstAppAuthContoupdate = new List<App_Auth_Contact__c>();
                lstAuthContacttodelete = new List<Auth_Contact__c>();

                for(App_Auth_Contact__c AppAuthCon: lstAppAuthCon)
                {
                    AppAuthCon.Contact__c = user.ContactId;
                    lstAppAuthContoupdate.add(AppAuthCon);
                }

                lstAuthContacttodelete.add(AuthContact);

            }
        }

        if(lstAppAuthContoupdate!=null && lstAppAuthContoupdate.size() > 0)
        {
            try
            {
                update lstAppAuthContoupdate;
            }
            catch(DMLException e)
            {
                system.debug(e.getMessage());
            }
        }

        if(!lstAuthContacttodelete.IsEmpty())
        {
            delete lstAuthContacttodelete;
        }
    }
}
  • Thanks a lot for letting me know the best practices for writting code... I would really appreciate if you would help me out with writing test class for this... – TestNS Sep 30 '13 at 5:04
  • The above code is giving me error ... when saving new user... Attempt to dereference a null object.. on line :--if(lstAppDelegatedContoupdate.size() > 0...........I tried giving if(lstAppDelegatedContoupdate.size() > 0 && lstAppDelegatedContoupdate != null) ...still not workinh – TestNS Oct 3 '13 at 10:54
  • Reverse them: if(lstAppDelegatedContoupdate != null && lstAppDelegatedContoupdate.size() > 0). Since && "short circuits", if the first part is false (i.e., the var is null), it will never try the second part, avoiding the NPE. Edited solution code above to match. – Jason Clark Oct 3 '13 at 13:11
2

! = isn't syntactically correct. It should be != (note the lack of a space).

  • Its working now – TestNS Sep 30 '13 at 6:45

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.