I have an APEX trigger that posts when an opportunity is closed won. Great, problem is its posting twice. From what I've read I believe this is to do with the fact that there are workflows that are triggered form an opportunity closing. Can this be dealt with referencing a class from within the trigger?

I also think that there will be an additional issue if that opportunity is edited and saved again in the future it will post the same post.

My ideal is that there is a post just once when an opportunity is closed won.

The code I have currently is:

trigger ChatterWonOpportunity on Opportunity (after update) {

    Opportunity oldOpportunity = trigger.old[0];
    Opportunity newOpportunity = trigger.new[0];
    Date today = date.today();
    if((oldOpportunity.StageName != 'Closed Won' && newOpportunity.StageName == 'Closed Won') || (newOpportunity.StageName == 'Closed Won' && newOpportunity.CloseDate == today)){
        String oppURL = URL.getSalesforceBaseUrl().toExternalForm() + '/' + newOpportunity.id;
        String status = '#Winning - We just won ' + newOpportunity.Name + '!';
        FeedItem post = new FeedItem();
        post.ParentId = newOpportunity.Id;
        post.Title = newOpportunity.Name;
        post.Body = status;
        post.LinkUrl = oppURL;
        post.Type = 'LinkPost';
        insert post;

Any help here much appreciated!


You can create a 'run once' class to keep it from running twice, I believe.

public Class CheckRecursive { private static boolean run = true; public static boolean runOnce() { if (run) { run = false; return true; } else { run = true; return false; } } }

And then you just do this in your trigger:

if (Trigger.isUpdate && CheckRecursive.runOnce()) { // your update code }

I'm using this in a project, and works like a charm.


Also, if I were you I would modify your code so it could work with multiple values, instead of getting only the first element that is passed to the trigger. Imagine that in the future you may create some action that closes multiple opportunities at the same time. A trigger that handles multiple entries will be much more efficient. And this is not hard to code at all. All you need to think is that you need the id of the opportunities that were updated, and the trigger.new already gives you that. With those ids, you can query the object table in SF and update the fields that you need.

  • Great, thanks for your reply. I'm getting an error though when trying to add the if(Trigger.isUpdate && Check Recursive.runOnce()). Its telling me the if is an unexpected token? – user3480962 Mar 31 '15 at 14:58
  • If you copy-pasted the code, I think its because you put "Check Recursive.runOnce()" with a whitespace between 'Check' and the rest. "CheckRecursive" is the class name and should not have spaces on it. – Renato Oliveira Mar 31 '15 at 15:21
  • Ah no sorry, there is no space in my code - if (Trigger.isUpdate && CheckRecursive.runOnce()) I've also tried typing it all from scratch and I get the same result – user3480962 Mar 31 '15 at 15:28
  • I really don't know what can be causing this. For me it works perfectly. Maybe you should check the CheckRecursive class for type errors instead. – Renato Oliveira Mar 31 '15 at 15:48

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.