Wednesday, November 19, 2014

Series introduction of jBPM 6.x (1)-Use Email notification of human task

It is a very common use case where the task owner get notified if he does not start task in certain time, or he does not complete it in certain time. BPMS 6 or jBPM 6 provides an out of the box email notification feature. But the docs are very few. Here I use an example to show you how to use it.

PS: application server : jboss as 6.2



Overview

The sample has only one User task. This task must be finished in certain time.


Let's click the Notifications in properties panel.

Here we add 2 notifications: not-started and not-completed. The “Expires At” is the duration to fire the notification event. We input “1m” and “2m”. For test purpose, the notification event will be fired if the task is not started within 1 minute, and fired again if it is not completed within 2 minutes. In real cases, you can user “h” or “d” which means hours and days respectively.
The From, Reply To, and To are user names being used when sending Email. Input your user id in field “To”.
Subject and Body are texts you want for the email. You may use process variables and task variable when setting values for those fields. Here is my example for Body field.
<html>
        <body>
                <b>You have been assigned to a task (task-id ${taskId})</b><br>
                Important technical information that can be of use when working on it<br/>
                - process instance id - ${processInstanceId}<br/>
                - work item id - ${workItemId}<br/>
                
                <hr/>
                Here are some task variables available
                <ul>
                        <li>ActorId = ${doc['ActorId']}</li>
                        <li>GroupId = ${doc['GroupId']}</li>
                        <li>Comment = ${doc['Comment']}</li>
                </ul>
                <hr/>
                Here are all potential owners for this task
                <ul>
                $foreach{orgEntity : owners}
                        <li>Potential owner = ${orgEntity.id}</li>
                $end{}
                </ul>
                
                <i>Regards from jBPM team</i>
        </body>
</html>

Configure default Email session

This notification feature uses default Email session. We need to configure it properly in Jboss standalone.xml (or standalone-full.xml, depends on your favorable one).
Find the mail subsystem and update the jndi-name as follows.
<subsystem xmlns="urn:jboss:domain:mail:1.1">
<mail-session jndi-name="java:/mail/jbpmMailSession">
<smtp-server outbound-socket-binding-ref="mail-smtp"/>
</mail-session>
</subsystem>
Make sure the there is a socket-binding as follows.
<socket-binding-group name="standard-sockets" ... >
...
<outbound-socket-binding name="mail-smtp">
<remote-destination host="localhost" port="25"/>
</outbound-socket-binding>
</socket-binding-group>
If you are using other host for your SMTP server, you need to change the host and port accordingly. Generally, Linux host has a SMTP service on port 25 – that is why the above configuration works in most cases (at least on my RHEL6 machine and Maitai production server).

Configure user info

Case one : Default UserGroupCallBack-JAASUserGourpCallBack

You may wonder what email address the notification is sent to - we only specify the name of user, such as “***”. If you try to input a full email address, such as ***@***.com, an error will happen. I think it should support such case. But unfortunately, jBPM does not support a full email address when sending notifications. Then where does the user information come from? The following file “userinfo.properties” hide the answer.
Path:#{your web application }/WEB-INF/userinfo.properties
Open the file and add following lines to make the example work.
Administrators=ruhan@redhat.com:en-UK:Administrators:[*]
*=*@redhat.com:en-UK:*
maitai-dev-list=maitai-dev-list@redhat.com:en-UK:maitai-dev-list

Case two : Custom UserGroupCallBack

This case, we use usergourpcallback: JAASUserGourpCallBack, if you costume the UserGourpCallBack, You need to follow a few steps:

1 Implementation custom UserGroupCallBack

  Open the beans.xml file in “jboss-home/standalone/deployments/business-central.war/WEB-INF”, you will see:
<alternatives>...
<class>org.jbpm.kie.services.cdi.producer.JAASUserGroupInfoProducer</class>
</alternatives>
This line specify which UserGroupInfoProducer implementation is used. The default is JAASUserGroupInfoProducer.
There is a DefaultUserInfo which is responsible for providing user information. You just need to design your implementation and hook it here. For example,
public class CustomUserGroupInfoProducer extends JAASUserGroupInfoProducer {
  private UserInfo userInfo = new CustomUserInfo(true);
  @Override
  @ApplicationScoped
  @Produces
  public UserInfo produceUserInfo() {
    return userInfo;
  }
}
And then modify the beans.xml as below:
<alternatives>...
<class>your.package.CustomUserGroupInfoProducer</class>
</alternatives>
2 Implementation custom UserInfo
  For example,
public class CustomUserInfo implements UserInfo{
@Override
    public String getDisplayName(OrganizationalEntity entity) {
        String name = entity.getId();
        if (name.trim().equals("Administrator")) {
            return name;
        }
        if (entity instanceof User) {
        //your logic
        }
        return null;
    }

 @Override


        public Iterator<OrganizationalEntity>
    getMembersForGroup(Group group) {

            List<OrganizationalEntity> members = new
    ArrayList<OrganizationalEntity>();


            if (group.getId().equals("Administrators")) {

                List<String> memberList = new ArrayList();

                memberList.add("Administrator");

                members = Lists.transform(memberList, new
    Function<String, OrganizationalEntity>() {

                    @Override
                    public OrganizationalEntity apply(String memberUid)
    {

                        User user =
    TaskModelProvider.getFactory().newUser();

                        ((InternalOrganizationalEntity)
    user).setId(memberUid);
                       return user;

                    }

                });
                return members.iterator();
            }
       //your logic

}
  @Override
        public boolean hasEmail(Group group) {
          //
        }
 @Override


        public String getEmailForEntity(OrganizationalEntity entity) {
            String name = entity.getId();
            if (name.trim().equals("Administrator")) {
                return "email address";
            }
            if (entity instanceof User) {
                //your logic
            }
            return null;
        }

          @Override

       public String getLanguageForEntity(OrganizationalEntity entity)
    {

           return "en-UK";

        }
}
Need to be aware of is group:Administrators and user : Administrator, these entity must be handled,Because of them is default group or user for start process.(version jBPM 6.0.1 and BPMS 6.0.1) .