I am new to Apex and not very sure about exception raising and handling/. Here is my use case i need to check whether owner has been changed and a box is checked. and if condition is true should not allow the change. If condition is false should carry on processing.

It is NOT an 'ALL or NONE' case.

Its a before update trigger.

I cannot prevent the update into database and partial processing at the same time. what change should i make in below I am actually trying to prevent the mass transfer of account ownership by criteria

public static void  checkOwnerChange(map <ID,account>Triggeroldmap,list<account>Triggerlist){
    List<account> toUpdate = new list<account> ();
    for (Account accountrecord: Triggerlist){
        Account oldaccount = TriggeroldMap.get(accountrecord.ID);
        if ((accountrecord.checkbox == true) &&
            (GEN_Utilities.recordType(accountrecord.recordTypeId) == 'check Account') &&
            (oldaccount.OwnerID != accountrecord.OwnerID)) 
            accountrecord.OwnerID = oldaccount.OwnerID ;
//some way to display a message saying this record cannot be changed

You can probably simplify this greatly and just use validation rules on the Account object to apply the validation. The error condition formula would look something like this:

    checkbox = true,
    RecordType.Name = 'check Account'
    ISCHANGED( OwnerId ) 

or In the trigger replace the comment with accountrecord.addError('Owner cannot be changed'); and then when you execute database.update(yourAccountList, false); the records in the account list which were error-free will be committed and the others will not.

You can then use the Save Result to display information about the records which were unsuccessful and why to the user.

Update: the mass transfer tool does not allow for partial processing of the records which are being transferred. It is always an all-or-none transaction.

My suggestion would be to use a validation rule like the one mentioned above and then describe the validation criteria in the error text so that the user who is performing mass transfer of Accounts can be successful in building filter criteria for the Accounts which you will allow to be transferred. Something to the effect of:

"Please filter your criteria with 'checkbox equals false' and 'RecordType.Name not equals check Account' when transferring accounts"

| improve this answer | |
  • Validation rule will not work for Mass transfer tool,ie the only reason why i am forced to go for trigger.also database.update can only be applied for after triggers-is that correct? – sfdc99999 Aug 7 '13 at 20:47
  • Database.update is a method which you can call from Apex which causes sObject record(s) to be updated. If there is a trigger on the sObject, the code within that trigger will be executed. Your trigger's code can be configured to execute before or after the platform performs validation and saves the record to the database (#4 in the docs ->). Related Documentation: Triggers and Order of Execution - Are you actually trying to prevent the mass transfer of account ownership by criteria? – Mark Pond Aug 7 '13 at 21:26
  • yeah i am trying to prevent mass transfer of account ownership by criteria – sfdc99999 Aug 7 '13 at 21:34
  • When i do this,and i try to update ownership by mass transfer tool say i have two records ,one which is fine for owner change and other not(as per this condition) but when do add.error statemnt,it simply dispays this error message on mass transfer tool page and stops me from changin owner for both records, Ideally i should still be able to transfer owner for one record and display error message for records that cannot be – sfdc99999 Aug 7 '13 at 21:56

First of all, even validation, normally, should be done as an after trigger. Because the transaction is atomic, even though you place addError() on the sobject, you will still cause the transaction to fail, in an all-or-none-true case. Which is the default behavior for Database.update() and the standalone update DML statement.

If by "partial processing" you mean in a batch of several records, your trigger is still allowing some records to succeed, even when some are failing, the reason is this: the transaction behavior is not normally controlled by the trigger, it is controlled by the code that called the DML which caused the trigger. I don't even know if there is a way to override the transaction behavior explicitly from within the trigger context. I don't think it is, but it might be worth a look.

One thought, though, if you do want to do that, is that you could, in case of failure of one record, go back through Trigger.new and call addError on all elements.

However, this would have the effect of causing only that batch of 200 to fail. So if someone were using data loader to load 1000 records you could have a scenario where 800 records succeed, and 200 fail because of what you are trying too do.

So my advice: don't do that!!! You're trying to fundamentally change the way transactions work from a place that doesn't want you to do that. It is an architectural choice that will cause potentially great headaches to developers and administrators who follow you.

| improve this answer | |
  • By Partial processing,i mean i am updating 10 records,out of which ,one i dont want to proceed,but other 9 should succeed. I thought we could see database.update(Boolean opt_allOrNone) and control this.But was not sure whether i can do this with custom exceptions? – sfdc99999 Aug 7 '13 at 13:27
  • 1
    No...this is not controlled from the trigger at all. Your trigger can't make the transaction be allOrNone false on the transaction that called it. That's the responsibility of the code that invokes the update in the first place. Custom exceptions give you a way to create an exception and they don't really have anything to do with the allOrNone behavior. – pchittum Aug 7 '13 at 13:31
  • hi i have updated my code,whenever condition is met,update the owner back.i would like to display to user a message saying Owner cannot be changed for AccountA .for each record ie failed?is that even possible – sfdc99999 Aug 7 '13 at 15:27
  • 1
    If a) you are reverting the ownerId field back to the value in Trigger.old and b) Using the UI Mass Transfer ownership tool, I'm betting that you'll need to have the trigger send an email to the running user with a list of links to all untransferable Accounts. Alternatively, you could build your own VF page and controller to do the mass transfer and then you would have total control and wouldn't need triggers at all – cropredy Aug 8 '13 at 1:27
  • ignore i am reverting back.but yeah i am using UI Mass transfer ownership tool and i want to give some message to user saying bellow records cannot be transferred because of this – sfdc99999 Aug 8 '13 at 11:17

Exceptions will break your operation, keeping in mind the bulk processing of records it is far more advised to speficy exceptions as errors on the individual records.

Have a look at the sObject methods, addError in specific.

record.addError('Owner cannot be changed');
record.field.addError('Owner cannot be changed');
| improve this answer | |
  • this will lead to failure of all the records,in that batch.its a all or none case? – sfdc99999 Aug 7 '13 at 13:28

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.