I have couple of objects(1 custom object called appointment and event object) which i am trying to syncronize. So i have 1 trigger each on each object which searches and updates the records. The issue is, these triggers will keep running recursively as everytime an appointmet is updated the event is also updated and the triggers keep firing and ofcourse salesforce does not accept it.
Any idea how to overcome this?
Thanks
Easiest way is to have an apex class containing a static boolean variable initialised to false. Then in each of your triggers you would check the state of this variable:
trigger MyTrigger on MyObject (after update)
{
if(CStaticTracker.bHasTriggerFired == false)
{
CStaticTracker.bHasTriggerFired = true;
// do your work and update the other object here
// shouldn't need this but let's play safe!
CStaticTracker.bHasTriggerFired = false;
}
}
The upshot being, of course, that when one of the triggers runs it'll set this variable to true, and prevent the recursive trigger from executing whatever logic is contained within the if statement. Of course this can still cause some cascading, but it will stop as soon as you don't call another update in one of the triggers.
Good luck!
Related
I have two triggers on a object.
One is managed package which I could not see or amend the content inside the trigger.
One is design by me.
I want to run my own created trigger before the managed package trigger. Could I control the sequence of the execution of the trigger.
Because it now always run the managed package trigger first. I would like to run my trigger first. I have been think for a few days. All colleague in my company could not know how to achieve this goal. Without fixing this issue, I couldn't be able to continue my work. Please help me out.
In the system there is no way to control the sequence of calls triggers, I think this limitation of unsafe programming. Do you have access to the package trigger? This is a really bad approach to have several triggers on a one object, better solution is to have a single trigger that will invoke various handlers. Then, on handlers level you can manage sequence of this handlers..
For example, this is simple trigger, which is invoked on different events and calls different methods with various logic:
trigger ContactTrigger on Contact (before insert, before update) {
/* Before Update*/
if(Trigger.isUpdate && Trigger.isBefore){
/*
here you can invoke different methods of different classes
(trigger handlers) in different sequences
*/
}
/* Before Insert*/
if(Trigger.isInsert && Trigger.isBefore){
//on other events you can use it too
}
}
}
In order to ensure that a handler can be invoked only after finishing of executing previous handler, you can use the state variables whose values will be changed at the end of handler, and you can check before calling other handlers. I hope this will help you in the future:)
I would like to trigger auto save on my model every time something changes, but only if the change came from the UI (i.e. the view). I mean, if the change came from the database, then there is no point in saving it again, it just came from the database...
However fetch and save can trigger change events (fetch because it brings potentially different state of the model, and save as it can bring the id for a newly created model)
So in the change event, I'd like to know what caused the change.
e.g. was it a call from the view?:
this.model.set("foo", "bar"); //triggers a change event as foo's value changed
Or a result of a sync operation?:
model.fetch(); //triggers a change event as the model changed in the DB
model.save(); //triggers a change event as the id was empty
Is there a way to tell them apart?
Once solution I thought of is wrapping view calls to the model's set with a setAttribute method, and triggering a custom changeDueToUIAction event, but I'm sure this has been solved before and I'm sure in a better way...
Or am I missing something altogether and the problem is that I ask the wrong question?
I'd say there are several custom solutions involving more or less boilerplate. And there is an easy one, though still adding a bit of boilerplate.
(Without any major change to Backbone) you can't know the source of the change (thinking about it, how would you have access to it in the Model#set method?). What you have access to in a listener is 2 objects. First one is the model which was changed. Second is the options you passed when calling the set method. So I guess you could do something like that:
// in the view
this.model.set('foo', 'bar', {'isFromUI': true});
// in your model
this.listenTo(this, 'change', function(model, flags) {
if(flags && flags.isFromUI) this.save();
});
I need help with a design issue and what happens in Batch Apex.
This is the scenario we have:
We have a territory object, then when you update a single field needs to update a field on UPTO hundreds of thoursands of contacts. To do this, I am using Batch Apex. And invoking it on the territory record before it’s updated.
Question:
Say the user updates the territory from A to B, and clicks save. This causes a big batch of contacts to get updated and take a while Then, he changes B to C. Are we guaranteed that the final update on all impacted records will be C? How come?
Or, is there a way to schedule your batch jobs? I’m looking into asyncApexJob and using that as a framework…
Is there a better design?
Batch Apex doesn't work the same way a Trigger works. The only way the situation described in your Question 1 would occur is if you were to call/execute a batch from a Trigger, and I would highly recommend avoiding that, if it's even possible.
(and 3.) Batches are typically scheduled to run over-night, or during off hours, using the Apex Scheduler. This is the recommended solution.
First, you will want to put the logic in the AFTER UPDATE trigger on the Territory object, not the BEFORE UPDATE section. As a general rule, if you need to update a field or value on the record/object that the trigger action is for (i.e. the Territory object in your case) then you use the BEFORE UPDATE or BEFORE INSERT section(s), and if you want to create/update/delete other records/objects (i.e. Contacts in your case) you use the AFTER UPDATE or AFTER INSERT section(s).
Second, I do not think there is anything wrong with initiating the batch apex process from your trigger.
For example, let us say you have a batch class called "BatchUpdateContactsBasedOnTerritory." And this class has three (3) key features:
it implements "Database.Stateful" in addition to "Database.Batchable"
it has a constructor method that takes a list of territories as an argument/parameter
it has a member variable to hold the list of territories that are passed in
Part of your batch class:
global list<Territory> TerritoryList;
global BatchUpdateContactsBasedOnTerritory(list<Territory> updatedTerritories){
TerritoryList = updatedTerritories;
}
Your trigger:
trigger TerritoryTrigger on Territory (after delete, after insert, after undelete, after update, before delete, before insert, before update)
{
if(trigger.isInsert)
{
if(Trigger.isBefore){
// before insert event not implemented
}
else if(Trigger.isAfter){
// after insert event not implemented
}
}else if(trigger.isUpdate){
if(Trigger.isBefore){
// before update event not implemented
}
else if(Trigger.isAfter){
// after update event - call batch class to process 1000 records at a time
Database.ExecuteBatch(new BatchUpdateContactsBasedOnTerritory(trigger.new),1000);
}
}else if(trigger.isDelete){
if(Trigger.isBefore){
// before delete event not implemented
}
else if(Trigger.isAfter){
// after delete event not implemented
}
}
else if(Trigger.isUnDelete){
// undelete event not implemented
}
}
When I pass {"silent":true} while setting an attribute in a Backbone model, why doesn't that just suppress the change:attribute event? What is the advantage of firing that event the next time an attribute is changed?
Update
Backbone 0.9.10 changed the behavior of passing { "silent": true }. From the changelog:
Passing {silent:true} on change will no longer delay individual
"change:attr" events, instead they are silenced entirely.
Browse the changelog here
This has confused me for some time as well.
The reason is that {silent:true} does not mean "Do everything as normal, but just don't trigger the event".
From various comments and answers by #jashkenas, what it seems to mean is "simply change the attribute value (and add it to the 'changedAttributes' hash), but defer all other "change-related" activities until later".
'silent' doesn't prevent the change event for that/those properties, it simply queues up the 'announcement' until the next change event is triggered.
So, its probably better named something like defer.
Relevant information:
https://github.com/documentcloud/backbone/pull/850
the point of a "silent" change is that it isn't considered a change from the models point of view. Later, when the change actually occurs, you get the full difference all at once.
https://github.com/documentcloud/backbone/issues/870
Because the point of silent changes is that you're allowed to twiddle with the internal state of your model, temporarily, without actually making a change. Later, when the attribute actually changes, the validation runs and events are emitted. It wouldn't make sense to emit an error event when making a silent change.
Update 4/7/2013
Note: I have not tested this to confirm behavior, this is just based on my reading of the release notes...
As of Backbone 0.9.10, the behavior described above has changed. In that version (and newer), silent:true suppresses the change:attr events entirely - not just delays them.
http://backbonejs.org/#changelog
In backbone 0.9.2 the set function runs validation before any changes are updated.
// Run validation.
if (!this._validate(attrs, options)) return false;
In case of {silent: true} option is passed, the validation code will not be executed.
if (options.silent || !this.validate) return true;
That means, model.set({value: 100}, {silent: true}); is able to set "invalid" value into model, so attributes are updated, but change event's are not firing.
It is useful, then you want to update some field and prevent whole mode validation, so if model is not yet completed, the change still propagated to attributes. But you usually you also want the view to show the change, so you have to manually call model.change() or model.trigger('change:value', model, value).
I want to listen change in my legacy system whenever there is any change in SF object (add/update/delete). So I have created outbound message and workflow. But in workflow I don't see any way to fire if object is deleted.
Is there anyway I can trigger outbound message on record delete? I know have heard that it can be done by trigger. But I don't want to write apex code for this.
To the best of my knowledge it cannot be done, the workflow actions are decoupled from the workflow rule (you can even reuse them) so they probably do not receive the transaction scope and when they execute the record is already gone and any reference inside action would point to a non-existing data. Thus the only way I know how to do it is via trigger.
Here is a workaround. However this will only be able to capture deletion made via std. Salesforce UI.
1.Create a custom checkbox field "Is Deleted"
2.Override the Del link with a custom VF page, that first updates the record status to "Is Deleted", and deletes the record.
3.Write workflow rule using the "Is Deleted" field.
Perhaps a compromise architecture would be to write an extremely small and simple after delete trigger that simply copies the deleted records in question to some new custom object. That new custom object fires your workflow rule and thus sends the outbound message you're looking for. The only issue with this would be to periodically clean up your custom object data that would grow in size as you deleted records from your other object. In other words, your "scratch" object would just need periodic cleaning - which could be done on a nightly schedule with batch Apex.
Here's a delete trigger that would do the trick using Opportunity as an example:
trigger AfterDelete on Opportunity (after delete)
{
List<CustObj__c> co = new List<CustObj__c>();
for(Opportunity o : Trigger.old)
{
CustObj__c c = new CustObj__c();
c.Name = o.Name;
c.Amount__c = o.Amount;
c.CloseDate__c = o.CloseDate;
c.Description__c = o.Description;
// etc.
co.add(c);
}
insert co;
}
It's not ideal but at least this would save you from having to code your own trigger-based outbound messages. These can only be done using the #Future annotation, btw, since callouts directly from triggers are forbidden. Hope that helps.
write a single email send in the trigger delete event. You have it in less than 1 hour.