0

I'm attempting to build a trigger that pulls the FullPhotoUrl from the User profile and set a field (FullPhotoUrl__c) on the SFDC_Employee__c object to the url. Here's the error I'm getting I'll paste the code underneath it.

System.NullPointerException: Attempt to de-reference a null object Trigger.EmployeeProfileImageHandler: line 16, column 1

trigger EmployeeProfileImageHandler on SFDC_Employee__c (before update) {
SFDC_Employee__c[] employees = (SFDC_Employee__c[])Trigger.new;

Set<String> employeelist = new Set<String>();
for (SFDC_Employee__c employee : employees) {
    employeelist.add(employee.User_ID__c);
}

User[] photos = [Select Name, FullPhotoUrl From User where ID IN :employeelist];
Map<String, User> photomap = new Map<String, User>();
for (User photo : photos) {
    photomap.put(photo.Name,photo);
}

for (SFDC_Employee__c employee : employees) {
    employee.FullPhotoUrl__c = photomap.get(employee.Name).FullPhotoUrl;
   }
}

I'm also getting an error on the test class which I've never run into

System.DmlException: Insert failed. First exception on row 0; first error: MIXED_DML_OPERATION, DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa): SFDC_Employee__c, original object: UserRole: []

Here's the test class code.

@IsTest
public class EmployeeProfileTest {
@TestSetup
static void TestEmployeeProfile() {
    UserRole r = new UserRole(DeveloperName = 'MyCustomRole', Name = 'My Role');
    insert r;

    Profile profileId = [SELECT Id FROM Profile WHERE Name = 'Standard User' LIMIT 1];

    User u = new User();
    u.FirstName = 'Test';
    u.LastName = 'UserLastName';
    u.ProfileId = profileId.Id;
    u.Email = '[email protected]';
    u.Username = '[email protected]' + System.currentTimeMillis();
    u.CompanyName = 'TEST';
    u.Title = 'title';
    u.Alias = 'alias';
    u.TimeZoneSidKey = 'America/Los_Angeles';
    u.EmailEncodingKey = 'UTF-8';
    u.LanguageLocaleKey = 'en_US';
    u.LocaleSidKey = 'en_US';
    u.UserRoleId = r.Id;
    insert u;       

    SFDC_Employee__c e = new SFDC_Employee__c();
    e.Name = 'Test UserLastName';
    e.Employee_User__c = u.Id;
    e.User_ID__c = u.Id;
    insert e;


    }
@IsTest
static void methodTest() {
    Test.startTest();
    Test.stopTest();
    }
}

2 Answers 2

1

You are getting exception here photomap.get(employee.Name) if your map doesn't contains the key then it gives you null as return and you are referring field value from it. So you need to put a null check here.

for (SFDC_Employee__c employee : employees) {
     if(photomap.containskey(employee.Name))
         employee.FullPhotoUrl__c = photomap.get(employee.Name).FullPhotoUrl;
   }
}

for your second operation Mixed DMl its related to DML operations on certain sObjects, sometimes referred to as setup objects, can’t be mixed with DML on other sObjects in the same transaction. This restriction exists because some sObjects affect the user’s access to records in the org. You must insert or update these types of sObjects in a different transaction to prevent operations from happening with incorrect access-level permissions. For example, you can’t update an account and a user role in a single transaction.

Mixed DML in Test class

Here are some workarounds to avoid this.

1
  • Thanks so much for the null check. I had already figured out the Mixed DML error and just moved the employee insert to be between StartTest(); and stopTest(); That fixed it as it was no longer in setup. I will post the revised code for the next person with the issue. Oct 22, 2017 at 6:41
1

Well your null pointer exception is because in your photomap you are using the key as photo.name (here - photomap.put(photo.Name,photo);) and then you are trying to access a value from this map by passing it a key of employee.Name (here - photomap.get(employee.Name).FullPhotoUrl;) which does not exist in the map and hence you get a null pointer exception when you try to access the FullPhotoUrl field. Your map key should be of same type and should exist in the map in order to access it.

If I think what your trying to achieve is to get the FullPhotoUrl for each employee then you should try this -

trigger EmployeeProfileImageHandler on SFDC_Employee__c (before update) {
SFDC_Employee__c[] employees = (SFDC_Employee__c[])Trigger.new;

Set<String> employeelist = new Set<String>();

for (SFDC_Employee__c employee : employees) {
        employeelist.add(employee.User_ID__c);
    }

User[] photos = [Select Name, FullPhotoUrl From User where ID IN :employeelist];
Map<String, User> photomap = new Map<String, User>();
for (User photo : photos) {
    photomap.put(photo.Name,photo);
}

for (SFDC_Employee__c employee : employees) {
    for (User photo : photos) {
        if(photo.Id==employee.User_Id__c){
            if(photomap.containsKey(photo.Name)){
                employee.FullPhotoUrl__c = photomap.get(photo.Name).FullPhotoUrl;
            }
        }
    }
}

Here I am matching to check if the User Id is same for the employee as well as the User (photo) (ie. the both records belong to the same User) and then if the value exists in the map or not, otherwise I would still get the null pointer exception if the value did not exist in the map. And after that we assign the value.

I would also suggest to change the map key to photo.Id as it will always be unique and is a better practise then using a name field.

Lastly, your second question already has an answer here.

8
  • Thanks for the help on the null pointer, and the suggestion for the key to be the photo.id. Oct 22, 2017 at 6:49
  • Your welcome Nathan Oct 22, 2017 at 6:52
  • Would you know of how to set the employee.User_ID__c in the apex based off of the user lookup that's selected? My current issue is that I need it to read the UserId before insert/update but if I use process builder to set the ID, it doesn't exist until after it's inserted/updated. Oct 22, 2017 at 7:37
  • Your question is a bit confusing, would you mind rephrasing it? And when exactly do you want to assign the employee.User_ID__c with the User.Id? Oct 22, 2017 at 8:02
  • I want to assign the employee.User_ID__c with the User.Id as the first thing. My question is basically that, how to assign employee.User_ID__c with the User.Id? Oct 22, 2017 at 8:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .