as a follow up to my earlier question I am now getting BeforeUpdate trigger errors when trying to insert attachments as it says the ParentId field is not writable.
so here below is the code that is supposed to copy all the attachments for the record from my custom object to the new record on the demand object in the BeforeUpdate event that fires when the record is updated:
// copy attachments:
List<Attachment> insertingAttachments = new List<Attachment>();
List<Attachment> lstAttachments = [SELECT Id, Body, Name, LastModifiedDate, contentType, OwnerId from Attachment where ParentId =:rq.Id];
for (Attachment att : lstAttachments){
Attachment newattch = new Attachment();
newattch = att.clone(false);
newattch.body = att.body; // required field
newattch.name = att.name;// required field
newattch.OwnerId=att.OwnerId;
newattch.parentId = newD.Id;
insertingAttachments.add(newattch);
}
if (insertingAttachments.size() > 0){
insert insertingAttachments;
}
// copy Notes:
List<Note> insertingNotes = new List<Note>();
List<Note> lstNotes = [SELECT Id, Title, ParentId, LastModifiedDate, createdbyid, body FROM Note where ParentId =:rq.Id];
for (Note eachNote : lstNotes){
Note newDemandNote= new Note();
newDemandNote.Body = eachNote.Body;
newDemandNote.Title=eachNote.Title;
newDemandNote.Id = eachNote.Id;
//newDemandNote.createdBy = string.valueOf(eachNote.CreatedById);
//newDemandNote.createdBy = eachNote.OwnerId;
newDemandNote.ParentId = newD.Id;
insertingNotes.add(eachNote);
}
if (insertingNotes.size() >0){
insert insertingNotes;
}
the error I am getting is:
Apex trigger System_Change_Request_Events caused an unexpected exception, contact your administrator: System_Change_Request_Events: execution of BeforeUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, attachment_before_insert: execution of BeforeInsert caused by: System.NullPointerException: Attempt to de-reference a null object Trigger.attachment_before_insert: line 39, column 1: []: Trigger.System_Change_Request_Events: line 310, column 1
UPDATE - here is the trigger code for isUpdate:
if (Trigger.IsUpdate && trigger.isbefore)
{
system.debug('(Trigger.IsUpdate && trigger.isbefore) BLOCK');
for (Request_for_System_Change__c rq : Trigger.new) {
system.debug('"for (Request_for_System_Change__c rq : Trigger.new) {" BLOCK');
// Access the "old" record by its ID in Trigger.oldMap
Request_for_System_Change__c oldrecord = Trigger.oldMap.get(rq.Id);
system.debug('step 4 Record Type=' + oldrecord.RecordType.Name);
system.debug('in trigger get LineManagerName');
string lineManagerName = [SELECT Name from User where Id =: rq.Manager__c].Name;
system.debug('in trigger Line Manager name for Demand: ' + lineManagerName);
if (rq.RecordTypeId == systemChangeRecordType)
{
if (rq.Status__c != OldRecord.Status__c && rq.Status__c == 'Convert to Demand') // && rq.RecordTypeId == systemChangeRecordType )
{
rq.Skip_Validation__c=true;
system.debug('trigger CONVERT TO DEMAND step 2a SYSTEM CHANGE REQUEST - Approved and create demand for '+ systemChangeRecordType);
apm2__Demand__c newD = new apm2__Demand__c();
//+ oldrecord.RecordType.Name + '
newD.Demand_request_date__c = rq.Date__c;
newD.Project_Department__c = 'Systems';
newD.Demand_Title__c = rq.Request_Title__c;
newD.apm2__Criticality__c = rq.Request_Priority__c;
newD.Demand_Requested_by__c = lineManagerName;
newD.Prioritisation_points__c = rq.Benefits_Reasons__c;
newD.Demand_request_date__c = system.today();
newD.apm2__Business_Driver__c = rq.Benefits_Reasons__c;
newD.Demand_Status__c = 'New';
newD.Originating_Request__c=rq.Id;
newD.Assigned_Resource__c=rq.Assigned_resource_for_demand__c;
newD.apm2__Demand_Type__c = 'Enhancement Request';
// rq.Description_of_change_requested__c.length()>=149 ? rq.Description_of_change_requested__c.substring(0,150) :rq.Description_of_change_requested__c
string sDesc;
integer iLen = rq.Description_of_change_requested__c.length();
if (iLen>=149){
sDesc= rq.Description_of_change_requested__c.substring(0,150);
}else {sDesc= rq.Description_of_change_requested__c;}
newD.apm2__Description__c = ' Systems Change Request (' + oldrecord.Name + ') \r\n' + sDesc +' ... (see Request for full description)' ;
newD.Extended_Description__c =
rq.Description_of_change_requested__c + ' \r\nExpected outputs:\r\n ' + rq.Expected_outputs__c
+ ' \r\nLegal / Regulatory / Compliance impact:\r\n ' + rq.Legal_Regulatory_Compliance_impact__c ;
newD.Additional_Information__c = rq.Anticipated_benefits_reason_for_change__c + ' \r\n' + rq.Additional_information_comments__c;
newD.Department_Requested_by__c = rq.Department_Name_String__c;
newD.Systems_Affected__c=rq.Systems_Affected__c;
insert newD;
rq.Demand__c = newD.Id;
rq.Demand_Name__c=[select name, id from apm2__Demand__c where Id=:newD.Id].Name; //newD.Name;
system.debug('New demand ID: ' + newD.Name);
rq.Status__c='Converted';
system.debug('Status: ' + rq.Status__c);
system.debug('Demand: ' + rq.Demand__c);
// now lock the record to prevent tampering... // Lock the request
// Lock the request
// Approval.LockResult lock(Id recordId)
// System.ApprovalProcess Approval=new System.ApprovalProcess();
// Approval.lock(rq.Id);
// Approval.LockResult = Approval.lock(rq.Id);
// Lock the request
//Approval.lock(rq.Id);
// copy Notes:
List<Note> insertingNotes = new List<Note>();
List<Note> lstNotes = [SELECT Id, Title, ParentId, LastModifiedDate, createdbyid, body FROM Note where ParentId =:rq.Id];
for (Note eachNote : lstNotes){
Note newDemandNote= new Note();
newDemandNote.Body = eachNote.Body;
newDemandNote.Title=eachNote.Title;
newDemandNote.Id = eachNote.Id;
//newDemandNote.createdBy = string.valueOf(eachNote.CreatedById);
//newDemandNote.createdBy = eachNote.OwnerId;
newDemandNote.ParentId = newD.Id;
insertingNotes.add(eachNote);
}
if (insertingNotes.size() >0){
insert insertingNotes;
}
// copy attachments:
List<Attachment> insertingAttachments = new List<Attachment>();
List<Attachment> lstAttachments = [SELECT Id, Body, Name, LastModifiedDate, contentType, OwnerId from Attachment where ParentId =:rq.Id];
for (Attachment att : lstAttachments){
Attachment newattch = new Attachment();
newattch = att.clone(false);
newattch.body = att.body; // required field
newattch.name = att.name;// required field
newattch.OwnerId=att.OwnerId;
newattch.parentId = newD.Id;
insertingAttachments.add(newattch);
}
if (insertingAttachments.size() > 0){
insert insertingAttachments;
}
to clarify, line 310 is insert insertingAttachments;
UPDATE: here is the trigger attachment_before_insert on Attachment:
trigger attachment_before_insert on Attachment (before insert) {
if (Trigger.isBefore && Trigger.isInsert)
{
PPTriggerUtils triggerUtils = new PPTriggerUtils();
triggerUtils.handleAttachmentBeforeInsert(Trigger.new);
}
/*//Build list of Ids to be excluded from file check
set<string> ExcludedIds = new set<string>();
//Project Object
for(apm2__Project__c p:[select Id, Name from apm2__Project__c]){
ExcludedIds.add(p.Id);
}
//Project Task Object
for(apm2__Project_Task__c pt:[select Id, Name from apm2__Project_Task__c]){
ExcludedIds.add(pt.Id);
}
//Demand Object
for(apm2__Demand__c d:[select id, Name from apm2__Demand__c]){
ExcludedIds.add(d.Id);
}
//Change Control Object
for(Change_Control__c cc:[select id, Name from Change_Control__c]){
ExcludedIds.add(cc.Id);
}*/
for(Attachment a:trigger.new){
//Set check attachment to true
boolean CheckFileType = true;
Id ids = a.ParentId;
Schema.SObjectType ObjectName = ids.getSObjectType();
if( string.valueOf(ObjectName) != 'Case' &&
string.valueOf(ObjectName) != 'Credit_Case__c' &&
string.valueOf(ObjectName) != 'Loan_Application__c')CheckFileType = false;
//Is user the API user?
if( Userinfo.getUserName().contains('apiuser@bankofcyprus.co.uk') ||
Userinfo.getUserName().contains('buser@bankofcyprus.co.uk')
)CheckFileType = false;
//If Checkfiletype equal true then check attachment contentType and then name.
if(CheckFileType == true){
if(string.valueOf(ObjectName) == 'Case' || string.valueOf(ObjectName) == 'Credit_Case__c'){
//Checks if a file is a ZIP file
if(a.ContentType == 'application/x-zip-compressed'){
a.adderror('ZIP files cannot be uploaded into Salesforce');
}
//Checks if a file is a HTML file
if(a.ContentType == 'text/html'){
a.adderror('HTM/HTML files cannot be uploaded into Salesforce');
}
//If you cannot check by contentType
if(a.Name.contains('.')){
list<string> sWrd = a.Name.splitByCharacterTypeCamelCase();
integer i = sWrd.size()-1;
if(i>=0){
string ext = sWrd[i];
//Check if file is Rich Text Format
if(ext.toLowerCase() == 'rtf')a.adderror('RTF files cannot be uploaded into Salesforce');
//Check if file is Csv Format
if(ext.toLowerCase() == 'csv')a.adderror('CSV files cannot be uploaded into Salesforce');
//Check if file is Csv Format
if(ext.toLowerCase() == 'msg')a.adderror('MSG files cannot be uploaded into Salesforce');
//Check if file is Csv Format
if(ext.toLowerCase() == 'zip')a.adderror('ZIP files cannot be uploaded into Salesforce');
}
}
}
else if(string.valueOf(ObjectName) == 'Loan_Application__c'){
//Checks if a file is not a pdf file
integer endP = a.Name.length();
integer staP = endP - 4;
if(a.name.substring(staP,endP).touppercase() != '.PDF'){
a.adderror('Only PDF documents can be uploaded');
}
}
}
}
}
and line 39 is Schema.SObjectType ObjectName = ids.getSObjectType();
so it doesn't like the idea of an insert into the attachments table referencing a newly inserted record in the Demand object during a Before_Update...
so what am I missing here, surely I can copy the notes and attachments?
attachment_before_insert
- that is where I would look first - when you clone these attachments, you'll fire the before insert trigger on the clones – cropredy Feb 18 '16 at 2:46!myList.isEmpty()
beforeDML
is unnecessary, but here it does tell us the list isn'tnull
, or you would get yourNullPointerException
there. Error is definitely in the other trigger. – Adrian Larson♦ Feb 24 '16 at 14:51insertingAttachments
is null then before this lineif (insertingAttachments.size() > 0)
will give error. – Tushar Sharma Feb 25 '16 at 11:45