Saturday 19 November 2011

Bypass Validation Rules from Apex

Today's post concerns a topic that crops up pretty frequently on the Developerforce Discussion Boards - how to allow apex code to bypass validation rules.

In  my example scenario, I've created a validation rule against the Contact standard object that checks either the contact's email address or phone number has been provided:

Thus when I attempt to create a Contact via the UI, if I don't provide one of these pieces of information I receive an error message:


All well and good.  However, what about the situation where I am creating a Contact programmatically? In this case the validation rule is still applied:


Obviously creating via the system log is a contrived example, but in practice I may be receiving the details from an external system as part of an integration (via an apex web service) or data migration (via the Apex Data Loader), and the information may simply not be available in that system.  If its a data migration, I could  disable the validation rule for the duration, but if its a real-time integration that isn't an option.

The solution I came up with was to provide a mechanism for the record itself to indicate how it was being created/edited and to take that into account for in the validation rule.

The first step in the solution is to create a new custom field on the Contact object - a checkbox that if set to true indicates the record is being processed in an apex context.  This checkbox is not made available on any page layouts, as we don't want regular UI users to be able to check it.


Next, change the validation rule to allow both the email and phone fields to be empty if the apex context field is set to true:


Its tempting at this time to think that the problem is now solved - the Apex Context field can simply be set to true and the validation rule will allow the record through.  However, the record will then be saved to the database with the Apex Content field set to true, and the next time that a user edits the record in the UI, the validation rule will be bypassed - not the behaviour I am looking for.  Therefore I've created a workflow rule and associated field update to unset the checkbox whenever it is found to be set.

Workflow rule:


Field update:


and that's all there is to it.  Now I can create a contact via the system log without providing the email or phone field:


But if I then navigate to that contact via the UI and attempt to edit the record without providing these fields, the validation rule blocks this:



30 comments:

  1. Hey Bob, great post; a clear solution to the problem that a lot of people seem to talk about. I think it's important to also highlight why people have these rules in the first place if they are willing to turn them off in certain circumstances.

    In your example if you asked people why they wanted to ensure there was a phone number they where say something like: "all contacts must have a phone number associated with them". That in itself is great - it's a business rule and it's clear, it's well defined and it's enforceable - heck there's probably even code and processes written against it. Then six months down the line they come and say "we have a whole of contact data that we want to load but it doesn't work because not all of the contacts have phone numbers" - and hey presto, we end up in this situation where by we need to "temporarily" disable a validation rule. So what has actually happened in this situation - has it become acceptable to not have a phone number associated with a contact, apparently so, so should we disable the rule completely? Apparently not. Instead we're left with terribly inconsistent data. Imagine now trying to edit the name of one of these imported contacts through the UI - you can't because the validation rule wants a phone number, but we don't have a phone number because the data didn't exist; we're trapped.

    Don't get me wrong - you've got an elegant solution to a common problem I just think that we, as responsible developers/analysts shouldn't be jumping to a code solution straight away. Instead we should question the validity of the data, therefore the need (or not) for the validation rule and the longer term consequences of implementing something like this.

    Simon

    ReplyDelete
  2. Hi Simon,

    Good to hear from you again. I've tended to use this when I'm migrating from a legacy system. In this siituation it's usually a case that we didn't have this business rule, so now we have a load of data that isn't much use. Therefore we will allow it to be loaded into the new system, but our rule going forward is that we must have this information. This means that of someone is updating the contact information, while they are there they can find out the email or phone number - presumably because they are actually speaking to the contact.

    ReplyDelete
  3. (comments from iPad sem tricky!)
    I agree that it's not always the greatest experience for the next user, but sometimes customers take the view that the salespeople entered the data missing vital fields in the first place, so they can clean it up as they go along.

    ReplyDelete
  4. In my mind loading invalid data into a system is an illogical thing to do as it always has broader and longer reaching consequences than initially imaged. Having said that I more than appreciate that requirements/customers aren't always logical and as such we need to find ways to work around these difficulties.

    ReplyDelete
  5. There's also adoption to consider. If you tell users you aren't going to load their existing contact data you stand a good chance of them sticking with their old system.

    ReplyDelete
  6. Hello Bob, I had this exactly same issue when we needed to import data from our legacy systems. Now if it's necessary again in the future, I can use this strategy.

    By the way, another solution that I read about was to use a specific profile, for instance, a System Administrator or even creating one for this dataload job, and then updating the validation rules to take it into account. I think it should be very similiar to this example.

    Regards,
    Jorge Mimica

    ReplyDelete
  7. Crap!!!! How it will work, After workflow update the validation rules get fire again. Then ?????

    ReplyDelete
  8. According to the apex docs, only standard validation is run again, not custom validation rules. That's the behaviour that I see when I test this.

    ReplyDelete
  9. Hi Bob,

    Thanks much...I had the same issue.Your thinking helped me a lot.

    ReplyDelete
  10. Nice post Bob! Sorry I'm late in reading it!

    Is a custom setting not the best/simplest approach for this kind of thing?

    I hope that Salesforce enhances this area in the future, it would be nice to have the ability to select Profiles/Roles/Users like the folders on a per validation rule/workflow rule basis

    ReplyDelete
  11. Custom setting is one way of achieving this. However, it doesn't give the granularity that I required at the time I wrote this post - I just presented a simplified example.

    ReplyDelete
  12. Bob,
    I am currently looking for a solution like this for a trigger I have that keeps getting blocked by validation rules. The validation rules have criteria to ignore the System Admin profile but that doesn't seem to be working for the Trigger. Any idea why telling it to ignore the system admin profile isn't working?

    Thanks,
    Amanda

    ReplyDelete
    Replies
    1. You should be able to bypass a validation rule based on the profile of the user making the change. I'd suggest you post a question to Salesforce Answers or the Developer Force discussion boards.

      Delete
    2. Ah, you answered it right there. I thought the trigger would run as the system admin, not the user who made the change.
      Thanks,
      Amanda

      Delete
  13. Hello Bob,

    I am developing an AppExchange app that would fetch data from a webservice and store it in database. On a button click, the record would be created into a lead record. Is there any workaround for getting records created without any validation rules or required field errors?

    One workaround that I can think of is to redirect user to lead edit screen and populate values on lead fields using url query parameters. But that can be tricky as lead field ids will be different in different orgs for custom fields. We can workaround this by using some custom settings which will store lead field ids for each org., but that would be hassle for non-technical customer and beats user friendliness of app.

    Any solution to my scenario you can suggest?

    Regards,
    Mustafa

    ReplyDelete
  14. HI Bob,

    Is there a way that we can skip the stadard email format validation in contact.

    I am developing an AppExchange app that would fetch data from an ERP system and store it in SFDC.the existing data has invalid emails in the ERP system.now the contacts are not getting insertedd because of invalid emails.

    thanks

    ReplyDelete
  15. Hi BOb,

    How should we check this check box programmatically?

    ReplyDelete
  16. Hi Bob,

    Thank you for this post. I am having a similar issue. Can you take a look and provide any feedback when you have a moment.

    https://developer.salesforce.com/forums/?id=906F0000000BWSJIA4

    Thanks in advance.

    ReplyDelete
  17. Hi Bob,

    Great post. Really helped me today. Thanks a lot!

    ReplyDelete
  18. Hi Bob,

    Nice idea, thank you for sharing it.

    Maryem QADA

    ReplyDelete
    Replies
    1. Great post Bob.
      But, it will not resolve the problem for below scenario.

      Suppose we are updating some record through code and we are making that field true, it will allow us to save record without validation rule fired and after that workflow rule will set the field value to false., but after field update trigger will execute and if there is some use case where we are again setting the field value to true.., here is the problem, because this time workflow will not fire (according to Order of Execution) and the field value remain true.

      Delete
  19. Thanks Bob. You post help me to solve my issue.

    ReplyDelete
  20. Hi Bob,
    That's a great stuff provided by you
    I followed the same steps provided by you but my test class failed to run even.
    can you please help me out?

    Thanks,
    Appu

    ReplyDelete
  21. I've been able to implement this idea using Visual Workflow, great stuff.
    Thanks Bob

    ReplyDelete
  22. Great post Bob.
    But, it will not resolve the problem for below scenario.

    Suppose we are updating some record through code and we are making that field true, it will allow us to save record without validation rule fired and after that workflow rule will set the field value to false., but after field update trigger will execute and if there is some use case where we are again setting the field value to true.., here is the problem, because this time workflow will not fire (according to Order of Execution) and the field value remain true.

    ReplyDelete
  23. Hey Bob,

    I don't understand, even if you are trying to update that field to previous still it is updating same record and again validation exceptions will comes into the picture.

    I tried myself, it's working during contact update when i am trying to make apex field to previous again updating contact and throwing same errors.

    ReplyDelete
  24. You can save a step! Eliminate deactivating the checkbox after it's saved, by implementing the following:

    1) Instead of "Apex Context", name your checkbox "Toggle Me to Bypass Validation Rules"; and

    2) instead of "NOT(Apex_Context__c)", set your Validation Rule's error condition to "NOT(ISCHANGED(Toggle_Me_to_Bypass_Validation_Rules__c))".

    BOOM! You're done. With this logic, you toggle the checkbox's value to skip the Validation Rule--and you don't need to revert the checkbox after the record saves.

    ReplyDelete