cancel
Showing results for 
Search instead for 
Did you mean: 

Notify users of new tasks via Email

zfranken
Champ in-the-making
Champ in-the-making
I would like to notify users via email when they are assigned a task or are one of a group of candidate users.  This is fairly straight forward for a single user with a TaskListener, but I can't think of any way to get at the candidate users/groups and to let them know they have a task waiting to be claimed.  Anybody know of a way to do this?

Thanks.
8 REPLIES 8

zfranken
Champ in-the-making
Champ in-the-making
Since I posted, I found http://jira.codehaus.org/browse/ACT-32.  Hopefully this will include notifications for candidates as well as assignees.

I was hoping I could get it working with the listener below, but it appears that the task is not yet persisted when the listeners are fired so the taskService lookups fail.  Perhaps an additional event once the task is persisted would help.


public class NotificationListener implements TaskListener {

private static Logger log = Logger.getLogger(NotificationListener.class.getName());

@Override
public void notify(DelegateTask delegateTask) {
  TaskService taskService = ProcessEngines.getDefaultProcessEngine().getTaskService();
  List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(delegateTask.getId());
 
  for(IdentityLink link : identityLinks) {
   String type = link.getType();
   if(type.equals(IdentityLinkType.ASSIGNEE)) {
    log.log(Level.INFO,"========== NOTIFY User of assignment: " + link.getUserId() + " ==============");
   }
   if(type.equals(IdentityLinkType.CANDIDATE)) {
    log.log(Level.INFO,"========== NOTIFY User of assignment: " + link.getUserId() + " ==============");
   }
  }
}
}

trademak
Star Contributor
Star Contributor
Hi,

You can try casting the DelegateTask parameter to TaskEntity and then you should be able to get the candidate users and groups directly.

Best regards,

zfranken
Champ in-the-making
Champ in-the-making
Perfect! Thanks.  Here is my implementation for reference:


import java.util.List;
import java.util.logging.Logger;

import org.activiti.engine.ActivitiException;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.persistence.entity.IdentityLinkEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.task.IdentityLinkType;
import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;


public class NotificationListener implements TaskListener {

private static Logger log = Logger.getLogger(NotificationListener.class.getName());

@Override
public void notify(DelegateTask delegateTask) {
  TaskEntity task = (TaskEntity)delegateTask;
  String assignee = task.getAssignee();
  List<IdentityLinkEntity> identityLinks = task.getIdentityLinks();
 
  StringBuffer message = new StringBuffer("");
  message.append("You have a new assigned task. <br/><br/>");
  message.append("<a href=\"http://localhost:8080/activiti-explorer/#tasks/");
  message.append(task.getId());
  message.append("?category=inbox\">");
  message.append(task.getName());
  message.append("</a>");
 
  if(assignee != null && assignee.length() > 0) {
   User user = Context.getProcessEngineConfiguration().getIdentityService().createUserQuery().userId(assignee).singleResult();
   sendNotification(user, message.toString());
  }
 
  for(IdentityLinkEntity link : identityLinks) {
   if(link.getType().equals(IdentityLinkType.CANDIDATE)) {
    if(link.isUser()) {
     User user = Context.getProcessEngineConfiguration().getIdentityService().createUserQuery().userId(link.getUserId()).singleResult();
     sendNotification(user, message.toString());
    }
    if(link.isGroup()) {
     List<User> users = Context.getProcessEngineConfiguration().getIdentityService().createUserQuery().memberOfGroup(link.getGroupId()).list();
     for(User user : users) {
      sendNotification(user, message.toString());
     }
    }
   }
  }
 
}

protected void sendNotification(User user, String message) {

  HtmlEmail email = new HtmlEmail();
  try {
   email.setHtmlMsg(message);
   email.addTo(user.getEmail());
   email.setSubject("Activiti Assignment Notification");
   email.setFrom("[email protected]");

   setMailServerProperties(email);

   email.send();
  } catch (EmailException e) {
   throw new ActivitiException("Could not send e-mail:" + e.getMessage(), e);
  }
}

protected void setMailServerProperties(Email email) {
  ProcessEngineConfigurationImpl processEngineConfiguration = Context.getProcessEngineConfiguration();

  String host = processEngineConfiguration.getMailServerHost();
  if (host == null) {
   throw new ActivitiException("Could not send email: no SMTP host is configured");
  }
  email.setHostName(host);

  int port = processEngineConfiguration.getMailServerPort();
  email.setSmtpPort(port);

  String user = processEngineConfiguration.getMailServerUsername();
  String password = processEngineConfiguration.getMailServerPassword();
  if (user != null && password != null) {
   email.setAuthentication(user, password);
  }
}

}

pteki
Champ in-the-making
Champ in-the-making
one quick question, is this TaskListener.Notify() works, even if we create a task using restAPI? I have overridden the Notify and I'm getting this only when we do the create/assign through activiti UI, not through API. Did I miss something.

jbarrez
Star Contributor
Star Contributor
The task listener is part of the process definition, so it doesn't matter if it's done through Java / REST.
Can you give an example where you see it's not working (process xml + the api you're calling)

pteki
Champ in-the-making
Champ in-the-making
Here the URL and the sample JSON. BTW, we are using the alfresco's distribution.
http://localhost:8181/activiti-app/api/enterprise/process-instances

activiti-user: ABCDEF
activiti-user-value-type:userExternalIdType
{
    "processDefinitionId":"IC-Cash-Payment:13:1030028",
    "name":"ICO Cash 22",
    "values":
    {
        "account":"123456",
        "status":"active",
        "valueDate":"2015-12-21T01:00:00Z",
        "tradeType":"xxxx",
        "amount":"10000",
        "iij":"IIJ00000001",
        "clientReference":"CRxxxx",
        "paymentDetail":"ddddddddddd",
        "authorizationsNeeded":"true"
    }
}
the Notify method
[java]
@Override
       public void notify(DelegateTask task) {
              LOGGER.info(String.format("Received EVENT:[%1s] for TASK:[%2s]",task.getEventName(),task.getId()));
              //Debug print: Engine Details
              LOGGER.debug(String.format("\nTask [%1s] Listener\n\tEngineServices: {%2s}\n\tRepository Service: {%3s}",
                           task.getId(),
                           task.getExecution().getEngineServices().toString(),
                           task.getExecution().getEngineServices().getRepositoryService().toString()                                         
                           ));
              //Debug print: Process Details
              LOGGER.debug(String.format("\nTask [%1s] Process Details:{ProcessInstanceId: [%2s], ProcessDefinitionId: [%3s], DeploymentId: [%4s], ResouceName:[%5s]}",
                           task.getId(),
                           task.getProcessInstanceId(),
                           task.getProcessDefinitionId(),
                            task.getExecution().getEngineServices().getRepositoryService().getProcessDefinition(task.getProcessDefinitionId()).getDeploymentId(),
                            task.getExecution().getEngineServices().getRepositoryService().getProcessDefinition(task.getProcessDefinitionId()).getResourceName()));
    
            
              switch(task.getEventName().toString()){
                     case TaskListener.EVENTNAME_CREATE:
                           createMyTaskEntry(task,"In Progress");
                           break;
                     case TaskListener.EVENTNAME_COMPLETE:
                           createMyTaskEntry(task,"Closed");
                           break;                   
                     case TaskListener.EVENTNAME_ASSIGNMENT:
                           createMyTaskEntry(task,"Assigned");                  
                           break;                   
                     case TaskListener.EVENTNAME_DELETE:
                           createMyTaskEntry(task,"Cancelled");
                           break;                   
                     default:
                           LOGGER.info(String.format("No Processing Defined for EVENT:[%1s] for TASK:[%2s]",task.getEventName(),task.getId()));
              }

       }
[/java]

jbarrez
Star Contributor
Star Contributor
OK, nothing wrong there. And that task listener is in the process definition defined? It is also on your classpath of the server?

pteki
Champ in-the-making
Champ in-the-making
yes. the issue was encoding my restTemplate didn't set the encoding to UTF-8 and there was some character which made the failure.
Added the below line, made it work at the client side.
restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
Thanks for the help.