Showing posts with label Chatter users autofollow apex trigger mixed mode DML. Show all posts
Showing posts with label Chatter users autofollow apex trigger mixed mode DML. Show all posts

Sunday, 29 May 2011

Chatter Autofollow Users

The subject of today's blog post is auto-following users.  This can be useful if you have people who are important with your organization (or think they are and you have no choice but to agree with them) and you want to ensure that all new users follow them in chatter. Regular readers of this blog will no doubt be surprised to see that there is no Visualforce aspect to this!

The first part of the solution is to create a public group containing the Users to be followed - I've chosen to call mine "Auto Follow Users" and the only important user is me!

Next up is an after insert trigger on the user object, as shown below:

trigger ai_user on User (after insert) 
{
   ChatterAutofollow.AutofollowUsers(trigger.newMap.keySet());
}

Not much to the trigger as I'm handing off to a utility class method to actually carry out the work. Usually this is a matter of personal preference, but in this case it has to be done that way for reasons which will be explained later.

The utility class is shown below:

public class ChatterAutofollow
{
   // constant group name
   public static final String AUTO_FOLLOW_GROUP='Auto Follow Users';
 
 
   // method has to be @future as cannot mix setup/non-setup DML in the same transaction      
   @future
   public static void AutofollowUsers(Set<Id> userIds)
   {
      // set up the users that should automatically be followed
      List<User> usersToFollow=new List<User>();
 
      Group autoFollowGroup=[Select Id From Group Where Name = :AUTO_FOLLOW_GROUP];
    
      List<GroupMember> members=[Select Id, UserOrGroupId From GroupMember Where GroupId = :autoFollowGroup.id];
      List<EntitySubscription> entSubs=new List<EntitySubscription>();
    
      // loop the users that have been created
      for (Id userId : userIds)
      {
         // Loop through all members in a group
      for (GroupMember member : members)
      {
     EntitySubscription entSub = new EntitySubscription (parentId = member.UserOrGroupId,
                                     subscriberid = userId);
       entSubs.add(entSub);
       }
      }
      insert entSubs;
   }
}

The method has the @future annotation, and this is the reason why the work has to be done by a utility class. Apex doesn't allow setup (i.e. User) DML to be mixed with non-etup (i.e. chatter EntitySubscription) in the same transaction. While I'm not carrying out any setup DML in my code, as this trigger is invoked from the insertion of a User, another part of the platform certainly has done this. Thus the insertion of the EntitySubscriptions takes place asynchronously in a separate transaction.

The method itself is pretty straightforward. First the group details are retrieved:

Group autoFollowGroup=[Select Id From Group Where Name = :AUTO_FOLLOW_GROUP];
    
List<GroupMember> members=[Select Id, UserOrGroupId From GroupMember Where GroupId = :autoFollowGroup.id];

Next the subscription objects are created, by iterating the inserted user ids and for each of these, iterating the auto follow group members and creating an EntitySubscription to their feed. In accordance with best practice and being able to handle bulk mode triggers, the subscriptions are added to a list and inserted en-masse at the end of the processing.



for (Id userId : userIds)
// loop the users that have been created
{
   // Loop through all members in a group
   for (GroupMember member : members)
   {
     EntitySubscription entSub = new EntitySubscription (parentId = member.UserOrGroupId,
                                     subscriberid = userId);
     entSubs.add(entSub);
   }
}
insert entSubs;

To check everything works as expected,  I create a new user called Fred Blogger and receive a confirmation email that he is now following me: