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:

3 comments:

  1. Bob,

    Do you have any idea how this might be tweaked to prevent users from following specific groups. We have three company's that compete to some degree or another with each other and we don't want them to try and use chatter info to try and get a leg up on the other. I have searched high and low with no luck in finding anyone with any ideas of how to make this work. Thanks

    Bladen

    ReplyDelete
  2. Unfortunately you can't have triggers on chatter groups at the moment, so you can't tell when someone is following a group. Assuming you can't use private groups, the only way I can think of off the top of my head would be to run some scheduled apex on as short a cycle as you can to check the groups and kick out users that shouldn't be part of the group.

    ReplyDelete
  3. Hi Bob,

    I want a single user to follow all existing Chatter People. I also want to make sure that if a new user is added, this same user automatically follows them. Do you know how I could modify this solution to suit my situation?

    Thanks,

    Michael

    ReplyDelete