You need to sign in to do that
Don't have an account?

Question on complex APEX code that shows how to run after insert and after update triggers?
So i'm about 50% into my Learning Salesforce Development with Apex: Write, Run and Deploy Apex Code with Ease (English Edition) book and I'm stuck on the below code. I provide a text version under the image. The below code has no problems. When I create a new task nothing happens though and if I create a task with a Contact it has an issue that says: TaskTrigger: execution of AfterInsert caused by: System.NullPointerException: Attempt to de-reference a null object Trigger.TaskTrigger: line 14, column 1
Text version of the code from Learning Salesforce Development with Apex: Write, Run and Deploy Apex Code with Ease (English Edition):
trigger TaskTrigger on Task (after insert, after update) {
switch on Trigger.operationType {
when AFTER_INSERT {
Set<Id> contactIds = new Set<Id>();
For(Task t: Trigger.new) {
If(t.WhoId != null && String.valueOf(t.WhoId).startsWith('003')) {
contactIds.add(t.WhoId);
}
}
Map<Id, Contact> contactMap = new Map<Id, Contact> ([SELECT Id, No_Of_Open_Tasks__c FROM Contact WHERE Id in: contactIds]);
For(Task t :Trigger.new) {
If(contactMap.containsKey(t.WhoId)) {
contactMap.get(t.WhoId).No_of_Open_Tasks__c += 1;
}
}
Update contactMap.values();
}
when AFTER_UPDATE {
Set<ID> contactIds = new Set<Id>();
For(Task t : Trigger.new) {
If(t.IsClosed && !Trigger.oldMap.get(t.Id).IsClosed && t.WhoId != null && String.valueOf(t.WhoId).startsWith('003')) {
contactIds.add(t.WhoId);
}
}
Map<Id, Contact> contactMap = new Map<Id, Contact>([SELECT Id, No_Of_Open_Tasks__c FROM Contact WHERE Id in :contactIds]);
For(Contact con : contactMap.values()) {
Con.No_of_open_tasks__c = 0;
}
For(AggregateResult ar : [SELECT WhoId, Count(Id) total FROM Task WHERE IsClosed = false AND WhoId in :contactIds GROUP BY WhoID]) {
String who = String.Valueof(ar.get('WhoId'));
Decimal total = (Decimal)(ar.get('total'));
contactMap.get(who).No_of_Open_Tasks__c = total;
}
update contactMap.values();
}
}
}
trigger TaskTrigger on Task (after insert, after update) {
switch on Trigger.operationType {
when AFTER_INSERT {
Set<Id> contactIds = new Set<Id>();
For(Task t: Trigger.new) {
If(t.WhoId != null && String.valueOf(t.WhoId).startsWith('003')) {
contactIds.add(t.WhoId);
}
}
Map<Id, Contact> contactMap = new Map<Id, Contact> ([SELECT Id, No_Of_Open_Tasks__c FROM Contact WHERE Id in: contactIds]);
For(Task t :Trigger.new) {
If(contactMap.containsKey(t.WhoId)) {
contactMap.get(t.WhoId).No_of_Open_Tasks__c += 1;
}
}
Update contactMap.values();
}
when AFTER_UPDATE {
Set<ID> contactIds = new Set<Id>();
For(Task t : Trigger.new) {
If(t.IsClosed && !Trigger.oldMap.get(t.Id).IsClosed && t.WhoId != null && String.valueOf(t.WhoId).startsWith('003')) {
contactIds.add(t.WhoId);
}
}
Map<Id, Contact> contactMap = new Map<Id, Contact>([SELECT Id, No_Of_Open_Tasks__c FROM Contact WHERE Id in :contactIds]);
For(Contact con : contactMap.values()) {
Con.No_of_open_tasks__c = 0;
}
For(AggregateResult ar : [SELECT WhoId, Count(Id) total FROM Task WHERE IsClosed = false AND WhoId in :contactIds GROUP BY WhoID]) {
String who = String.Valueof(ar.get('WhoId'));
Decimal total = (Decimal)(ar.get('total'));
contactMap.get(who).No_of_Open_Tasks__c = total;
}
update contactMap.values();
}
}
}
trigger TaskTrigger on Task (after insert, after update) {
switch on Trigger.operationType {
when AFTER_INSERT {
Set<Id> contactIds = new Set<Id>();
For(Task t: Trigger.new) {
If(t.WhoId != null && String.valueOf(t.WhoId).startsWith('003')) {
contactIds.add(t.WhoId);
}
}
Map<Id, Contact> contactMap = new Map<Id, Contact> ([SELECT Id, No_Of_Open_Tasks__c FROM Contact WHERE Id in: contactIds]);
For(Task t :Trigger.new) {
If(contactMap.containsKey(t.WhoId)) {
contactMap.get(t.WhoId).No_of_Open_Tasks__c += 1;
}
}
Update contactMap.values();
}
when AFTER_UPDATE {
Set<ID> contactIds = new Set<Id>();
For(Task t : Trigger.new) {
If(t.IsClosed && !Trigger.oldMap.get(t.Id).IsClosed && t.WhoId != null && String.valueOf(t.WhoId).startsWith('003')) {
contactIds.add(t.WhoId);
}
}
Map<Id, Contact> contactMap = new Map<Id, Contact>([SELECT Id, No_Of_Open_Tasks__c FROM Contact WHERE Id in :contactIds]);
For(Contact con : contactMap.values()) {
Con.No_of_open_tasks__c = 0;
}
For(AggregateResult ar : [SELECT WhoId, Count(Id) total FROM Task WHERE IsClosed = false AND WhoId in :contactIds GROUP BY WhoID]) {
String who = String.Valueof(ar.get('WhoId'));
Decimal total = (Decimal)(ar.get('total'));
contactMap.get(who).No_of_Open_Tasks__c = total;
}
update contactMap.values();
}
}
does anyone have an APEX book that they recommend I hate reading a book and the author goes insane with power 100 pages in
Hi Brian, how did you manage to solve it? I am on the same page of the book right now... same error:
TaskTrigger: execution of AfterInsert caused by: System.NullPointerException: Attempt to de-reference a null object Trigger.TaskTrigger: line 25, column 1
I populate the "No of open task" field using a List instead of a Map but as the writer explains, this only works if you insert one task per contact
I will keep on trying
Hi Brian, I think the default value of 0 is missing, that is the reason for the error to show up
I tried setting up the value of "No_Of_Open_Tasks__c" to 0 and then it works
To clarify (for anyone reaching this matter), this would not work:
Integer tasks;
tasks += 1;
As "tasks" is stated as null:
But this would:
Integer tasks = 0;
tasks += 1;
system.debug(tasks);
Took me a while to find it out, I am learning APEX too 😉
Have a nice weekend