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
PrashantSakhujaPrashantSakhuja 

Apex Trigger Error: RECORD TYPE UPDATE: System.NullPointerException

Apex Trigger Error: RECORD TYPE UPDATE: System.NullPointerException: Attempt to de-reference a null object

 

Hi,

I am getting an error message with a trigger on case. Cant figure what I am doing wrong.

Thanks in advance for any help with this.

 

Scenario: Apex Trigger to update record type based on TYPE value on a case. Fetching record type ID where record type name is 'SR'

 

Error on Save:  

Error:Apex trigger Case_Record_Type_Update caused an unexpected exception, contact your administrator: Case_Record_Type_Update: execution of BeforeUpdate caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.Case_Record_Type_Update: line 22, column 34

 

I have tried with some changes in the below code but same error each time.

 

CODE:

 

 

trigger Case_Record_Type_Update on Case (before insert, before update) {

   for (Case cs : Trigger.new) {

      if ((Trigger.isInsert | Trigger.isUpdate) && cs!= null){  

          Schema.DescribeSObjectResult DSOR = Schema.SObjectType.Case;          

          Map<String,Schema.RecordTypeInfo> rtMapByName = DSOR.getRecordTypeInfosByName();

      

       if (cs.Type == 'Service Request') {

           if (cs.Status == 'Accept' | cs.Status == 'Disregard') {

             cs.Subject = 'Accept/Disregard';

             Schema.RecordTypeInfo rtByName = rtMapByName.get('SR');

             Id NewRecordTypeforCase = rtByName.getRecordTypeId(); <--- ERROR LINE

             cs.RecordTypeId = NewRecordTypeforCase;

 

         } // End If Accept/Disregard

      } // End If Service Request

 

    } // End If Not NUll check

  } // End For Loop on Case

} // End Trigger Block

 

 

 

 

DEBUG LOG:

 

*** Beginning SetAssetAccount on Case trigger event BeforeUpdate for 500T0000001fVim

20090902190242.983:Trigger.SetAssetAccount: line 8, column 2: SelectLoop:LIST:SOBJECT:Case
20090902190242.983:Trigger.SetAssetAccount: line 18, column 2: >>>>>Changed Asset IDs: {}

Cumulative resource usage:

Resource usage for namespace: (default)
Number of SOQL queries: 0 out of 20
Number of query rows: 0 out of 1000
Number of SOSL queries: 0 out of 0
Number of DML statements: 0 out of 20
Number of DML rows: 0 out of 100
Number of script statements: 6 out of 10200
Maximum heap size: 0 out of 200000
Number of callouts: 0 out of 10
Number of Email Invocations: 0 out of 10
Number of fields describes: 0 out of 10
Number of record type describes: 0 out of 10
Number of child relationships describes: 0 out of 10
Number of picklist describes: 0 out of 10
Number of future calls: 0 out of 10
Number of find similar calls: 0 out of 0
Number of System.runAs() invocations: 0 out of 0

Total email recipients queued to be sent : 0
Static variables and sizes:
SetAssetAccount:assetIds:4
SetAssetAccount:idx:4


*** Ending SetAssetAccount on Case trigger event BeforeUpdate for 500T0000001fVim

*** Beginning Case_Record_Type_Update on Case trigger event BeforeUpdate for 500T0000001fVim

20090902190242.991:Trigger.Case_Record_Type_Update: line 2, column 2: SelectLoop:LIST:SOBJECT:Case
System.NullPointerException: Attempt to de-reference a null object

Trigger.Case_Record_Type_Update: line 22, column 34


Cumulative resource usage:

Resource usage for namespace: (default)
Number of SOQL queries: 0 out of 20
Number of query rows: 0 out of 1000
Number of SOSL queries: 0 out of 0
Number of DML statements: 0 out of 20
Number of DML rows: 0 out of 100
Number of script statements: 11 out of 10200
Maximum heap size: 0 out of 200000
Number of callouts: 0 out of 10
Number of Email Invocations: 0 out of 10
Number of fields describes: 0 out of 10
Number of record type describes: 1 out of 10
Number of child relationships describes: 0 out of 10
Number of picklist describes: 0 out of 10
Number of future calls: 0 out of 10
Number of find similar calls: 0 out of 0
Number of System.runAs() invocations: 0 out of 0

Total email recipients queued to be sent : 0
Stack frame variables and sizes:
  Frame0
    rtByName:0
    rtMapByName:326
    cs:0
    DSOR:153


*** Ending Case_Record_Type_Update on Case trigger event BeforeUpdate for 500T0000001fVim

 

 

thanks

Prashant

 

Edit 1 and 2: Added intend on Code snippet.

 
Message Edited by PrashantSakhuja on 09-02-2009 04:42 PM
Message Edited by PrashantSakhuja on 09-02-2009 04:43 PM
Best Answer chosen by Admin (Salesforce Developers) 
PrashantSakhujaPrashantSakhuja
Ok. I have everything working now, I am still not sure what exactly worked.
Thanks IanR and Amphro for the help. 
Initially I thought it could be space between the "SR_Auto_New" vs "SR Auto New" but that should not have mattered for SR vs SR.
For any one else reading this:
  1. When you are using getRecordTypeInfosByName().get('XYZ') -->  the XYZ is Record Type Label and NOT the Record Type Name. The documentation in salesforce_apex_language_reference.pdf Page 232 is incorrect. It says rt.name but what works is the Record Label.
  2. If you still end up with an error, Try the code below to help you debug faster.

 

 

Schema.DescribeSObjectResult DSOR= Schema.SObjectType.Case;

Map<String,Schema.RecordTypeInfo>rtMapByName = DSOR.getRecordTypeInfosByName();

Set<String>rtMapByNameSet = rtMapByName.keySet();

 

for (stringrtMapByNameSetKey : rtMapByNameSet) {

     system.debug('rtMapByNameSetkey = ' + rtMapByNameSetKey);

     system.debug('rtMapByNamevalue = ' + rtMapByName.get(rtMapByNameSetKey));

     system.debug('Record ID for='+ rtMapByNameSetKey + ': ' + rtMapByName.get(rtMapByNameSetKey).getRecordTypeId());

     system.debug(Schema.SObjectType.Case.getRecordTypeInfosByName().get(rtMapByNameSetKey).getRecordTypeId());

} 
 
Notice that For loop is on the Set but the Map is used for getting the value of the key on Line 7.
 
Hope this Helps!! 

 
Message Edited by PrashantSakhuja on 09-03-2009 03:01 PM

All Answers

AmphroAmphro

Your first conditional doesn't do anything, it will always be true.

 

myMap.get('something') will return null if it can't find it. So on the error line, you are tring to acces a field on a null object. Try this.

trigger Case_Record_Type_Update on Case (before insert, before update) {
for (Case cs : Trigger.new) {
Schema.DescribeSObjectResult DSOR = Schema.SObjectType.Case;
Map rtMapByName = DSOR.getRecordTypeInfosByName();

if (cs.Type == 'Service Request') {
if (cs.Status == 'Accept' | cs.Status == 'Disregard') {
cs.Subject ='Accept/Disregard';
Schema.RecordTypeInfo rtByName = rtMapByName.get('SR');

if (rtByName != null) {
cs.RecordTypeId = rtByName.getRecordTypeId();
}
}
}
}
}
I dont think that will do what you want, but should get rid off the error. Let me know if it works.
PrashantSakhujaPrashantSakhuja

Amphro, you are right. rtByName happened to be null. I am curious why that would be.

I also checked that rtMapByName is not null so till that point I am ok. (Line 4 in your snippet)

 

The below line is the culprit. The syntax appears to be correct, there is no error on compile but during run time only.
Schema.RecordTypeInfo rtByName = rtMapByName.get('SR');

Below line works fine if I use the actual record ID instead of rtByName.getRecordTypeId();

cs.RecordTypeId = rtByName.getRecordTypeId();

Still looking for help....

IanRIanR

it looks like 'SR' is not in the map,

 

try putting in a debug to see what *is* in the map at runtime...

 

system.debug ( 'keyset = ' + rtMapByName.keySet() );

 

 

HTH, Ian

PrashantSakhujaPrashantSakhuja

Thanks for the pointer. I got the relevant log lines below. 'SR' does appear to be in the map so I am not sure what to look for now.

 

*** Beginning Case_Record_Type_Update on Case trigger event BeforeUpdate for 500T0000001fVim 20090902235452.850:Trigger.Case_Record_Type_Update: line 2, column 2: SelectLoop:LIST:SOBJECT:Case 20090902235452.850:Trigger.Case_Record_Type_Update: line 26, column 8: rtMapByName KeySet = {Master, SR, SR New Auto, SR ReadOnly, Ticket}

 

 

IanRIanR
Huh, that's weird...

I guess the next thing to check would be 'what object is in the map at that key?' - it appears that it is 'null', based on the original question, but maybe you could iterate through the keyset, and debug the object yielded by a get() for each key, might give you some clue??

e.g.

for (string key in map.keyset()) { system.debug('key = ' + key + ', value = ' + map.get(key)); }

 

PrashantSakhujaPrashantSakhuja

Will try this as soon as I am back to work (need my Eclipse)

 

However in the meanwhile, going through my original code, everything works fine If I harcode the recordtype ID.

Based on above, my assumption right now is that the object is not null.

 

In any case, Will post again after trying out you the below. Thanks for the help so far.

 

for (string key in map.keyset()) {
system.debug('key = ' + key + ', value = ' + map.get(key));
}

 

PrashantSakhujaPrashantSakhuja

Ok. So below is what I got from the debug log.

Nothing unusual there. This is what I would expect when the code would work!!

 

Time for some out of box thinking. ...

 

*** Beginning Case_Record_Type_Update on Case trigger event BeforeUpdate for 500T0000001fVim 20090903183803.176:Trigger.Case_Record_Type_Update: line 2, column 5: SelectLoop:LIST:SOBJECT:Case 20090903183803.176:Trigger.Case_Record_Type_Update: line 19, column 29: rtMapByName KeySet = {Master, SR, SR New Auto, SR ReadOnly, Ticket} 20090903183803.176:Trigger.Case_Record_Type_Update: line 20, column 29: SelectLoop:SET:String 20090903183803.176:Trigger.Case_Record_Type_Update: line 21, column 33: rtMapByNameSet key = Ticket 20090903183803.176:Trigger.Case_Record_Type_Update: line 22, column 33: , value = Schema.RecordTypeInfo[getName=Ticket;getRecordTypeId=01230000000GxG8AAK;isAvailable=true;isDefaultRecordTypeMapping=false;] 20090903183803.176:Trigger.Case_Record_Type_Update: line 21, column 33: rtMapByNameSet key = SR ReadOnly 20090903183803.176:Trigger.Case_Record_Type_Update: line 22, column 33: , value = Schema.RecordTypeInfo[getName=SR ReadOnly;getRecordTypeId=01230000000Gg7XAAS;isAvailable=true;isDefaultRecordTypeMapping=false;] 20090903183803.176:Trigger.Case_Record_Type_Update: line 21, column 33: rtMapByNameSet key = SR New Auto 20090903183803.176:Trigger.Case_Record_Type_Update: line 22, column 33: , value = Schema.RecordTypeInfo[getName=SR New Auto;getRecordTypeId=01230000000Gb2PAAS;isAvailable=true;isDefaultRecordTypeMapping=false;] 20090903183803.176:Trigger.Case_Record_Type_Update: line 21, column 33: rtMapByNameSet key = Master 20090903183803.176:Trigger.Case_Record_Type_Update: line 22, column 33: , value = Schema.RecordTypeInfo[getName=Master;getRecordTypeId=012000000000000AAA;isAvailable=true;isDefaultRecordTypeMapping=false;] 20090903183803.176:Trigger.Case_Record_Type_Update: line 21, column 33: rtMapByNameSet key = SR 20090903183803.176:Trigger.Case_Record_Type_Update: line 22, column 33: , value = Schema.RecordTypeInfo[getName=SR;getRecordTypeId=01230000000Gb2OAAS;isAvailable=true;isDefaultRecordTypeMapping=true;]

 

 

AmphroAmphro

What happens if you try this.

for (string key in map.keyset()) {
system.debug('key = ' + key + ', value = ' + map.get(key) + ', recordType = ' + map.get(key).getRecordTypeId());
}

 If that works, can you do,

map.get('SR').getRecordTypeId();

 

PrashantSakhujaPrashantSakhuja
Ok. I have everything working now, I am still not sure what exactly worked.
Thanks IanR and Amphro for the help. 
Initially I thought it could be space between the "SR_Auto_New" vs "SR Auto New" but that should not have mattered for SR vs SR.
For any one else reading this:
  1. When you are using getRecordTypeInfosByName().get('XYZ') -->  the XYZ is Record Type Label and NOT the Record Type Name. The documentation in salesforce_apex_language_reference.pdf Page 232 is incorrect. It says rt.name but what works is the Record Label.
  2. If you still end up with an error, Try the code below to help you debug faster.

 

 

Schema.DescribeSObjectResult DSOR= Schema.SObjectType.Case;

Map<String,Schema.RecordTypeInfo>rtMapByName = DSOR.getRecordTypeInfosByName();

Set<String>rtMapByNameSet = rtMapByName.keySet();

 

for (stringrtMapByNameSetKey : rtMapByNameSet) {

     system.debug('rtMapByNameSetkey = ' + rtMapByNameSetKey);

     system.debug('rtMapByNamevalue = ' + rtMapByName.get(rtMapByNameSetKey));

     system.debug('Record ID for='+ rtMapByNameSetKey + ': ' + rtMapByName.get(rtMapByNameSetKey).getRecordTypeId());

     system.debug(Schema.SObjectType.Case.getRecordTypeInfosByName().get(rtMapByNameSetKey).getRecordTypeId());

} 
 
Notice that For loop is on the Set but the Map is used for getting the value of the key on Line 7.
 
Hope this Helps!! 

 
Message Edited by PrashantSakhuja on 09-03-2009 03:01 PM
This was selected as the best answer
IanRIanR
Nice work :)
PrashantSakhujaPrashantSakhuja

Amphro, I saw your post after I posted the solution, but yes what I tried was very similar to what you posted for the debug.

Thanks again....