Creating custom notifications in Liferay
As I mentioned before, I’ve recently started working with the Liferay platform. I had some free time and decided I would spend it learning how to add custom notifications to one of the administrative portlets that contained a long-running process. So, I scoured the internet for any documentation on how to specify custom notifications in Liferay. What I found was this article (and various re-gur-gi-tations of the information). In the article, the author describes the following steps:
- Adding an XML file which defines the delivery types for the notification
- Adding a custom handler to produce the body of the notification
- This contains a hard-coded portlet ID
- Updating the liferay-portal.xml definition to include references to the custom definitions/handler
I wanted to take a slightly different approach. Liferay requires the custom handler to return the body of the notification but the XML file detailing the delivery types is not something I wanted to maintain. So, here is what I did to get custom notifications working without the XML file modifications.
First, I created the custom handler and overrode the GetBody and GetLink methods:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Override
protected String getBody(
UserNotificationEvent userNotificationEvent,
ServiceContext serviceContext) throws Exception {
JSONObject jsonObject =
JSONFactoryUtil.createJSONObject(
userNotificationEvent.getPayload()
);
String notificationTitle=jsonObject.getString("title");
String notificationDetails = jsonObject.getString("status");
String body = StringUtil.replace(getBodyTemplate(), new String[] {
"[$TITLE$]", "[$BODY_TEXT$]" },
new String[] {
"<strong>" + notificationTitle + "</strong>",
notificationDetails });
return body;
}
@Override
protected String getLink(
UserNotificationEvent userNotificationEvent,
ServiceContext serviceContext) throws Exception {
return super.getLink(userNotificationEvent, serviceContext);
}
protected String getBodyTemplate() throws Exception {
return "<div class=\"title\">[$TITLE$]</div>" +
"<div class=\"body\">[$BODY_TEXT$]</div>");
}
Next, I wanted to address the hard-coded portlet ID from the article so I created a public constructor that accepts a String of the portlet ID and calls the “setPortletId” function.
1
2
3
public CustomNotificationHandler(String portletId) {
setPortletId(portletId);
}
Once I had the handler finished, I set out to programmatically create the appropriate definitions…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
CustomNotificationHandler hndlr = new com.example.CustomNotificationHandler(
themeDisplay.getPortletDisplay().getId());
UserNotificationManagerUtil.addUserNotificationHandler(hndlr);
if(UserNotificationManagerUtil.fetchUserNotificationDefinition(
hndlr.getPortletId(),
ClassNameLocalServiceUtil.getClassNameId(hndlr.getClass().getName()),
UserNotificationDeliveryConstants.TYPE_WEBSITE).equals(null))
{
UserNotificationDefinition def =
new UserNotificationDefinition(
hndlr.getPortletId(),
ClassNameLocalServiceUtil.getClassNameId(
hndlr.getClass().getName()
),
0,
"Receive notification when this " +
"portlet does something INCREDIBLE." );
def.addUserNotificationDeliveryType(
new UserNotificationDeliveryType(
"Website",
UserNotificationDeliveryConstants.TYPE_WEBSITE,
true,
true)
);
UserNotificationManagerUtil.addUserNotificationDefinition(
hndlr.getPortletId(),
def);
}
Finally, I had to create and send add the actual message:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
JSONObject payload = JSONFactoryUtil.createJSONObject();
payload.put("status", "This is the extraordinary notification message.");
payload.put("title", "Tie Til");
payload.put("userId", CurrentUser.getUserId());
UserNotificationEvent notification =
UserNotificationEventLocalServiceUtil.createUserNotificationEvent(
CounterLocalServiceUtil.increment()
);
notification.setCompanyId(companyId);
notification.setUserId(CurrentUser.getUserId());
notification.setPayload(payload.toString());
notification.setDeliverBy(UserNotificationDeliveryConstants.TYPE_WEBSITE);
notification.setTimestamp(new Date().getTime());
notification.setArchived(false);
notification.setType(hndlr.getPortletId());
UserNotificationEventLocalServiceUtil.addUserNotificationEvent(notification);