Implementing Custom Notifications in a Portlet
Liferay custom notifications require a User Notification
Handler class that turns the notification into a nice HTML fragment that is
displayed to the user. Also Liferay wants us to define the notification types
that our portlet or application is creating in a definition file upfront.
<portlet>
<portlet-name>test-example</portlet-name>
<icon>/icon.png</icon>
<indexer-class>com.liferay.testexample.search.EmployeeSearchIndexer</indexer-class>
<user-notification-definitions>example-user-notification-definitions.xml</user-notification-definitions>
<user-notification-handler-class>com.example.notifications.ExampleUserNotificationHandler</user-notification-handler-class>
<header-portlet-css>/css/main.css</header-portlet-css>
<footer-portlet-javascript>/js/main.js</footer-portlet-javascript>
<css-class-wrapper>test-example-portlet</css-class-wrapper>
</portlet>
|
So the first thing we need to do is to define the location
of our class that extends BaseUserNotificationHandler class and definitions
inside liferay-portlet.xml. This can be done in liferay-portlet.xml like
this:
The important part is user-notification-definitions and user-notification-handler-class tags.
Now we need to actually define our notification inside that example-user-notification-definitions.xml.
This file should go into your docroot/WEB-INF/src folder.
Here is the example-user-notification-definitions.xml
:
<?xml version="1.0"?>
<!DOCTYPE user-notification-definitions
PUBLIC "-//Liferay//DTD
User Notification Definitions 6.2.0//EN" "http://www.liferay.com/dtd/liferay-user-notification-definitions_6_2_0.dtd">
<user-notification-definitions>
<definition>
<notification-type>${com.example.notifications.ExampleUserNotificationHandler.PORTLET_ID}</notification-type>
<description>receive-a-notification-when-example-triggered</description>
<delivery-type>
<name>email</name>
<type>${com.liferay.portal.model.UserNotificationDeliveryConstants.TYPE_EMAIL}</type>
<default>false</default>
<modifiable>true</modifiable>
</delivery-type>
<delivery-type>
<name>website</name>
<type>${com.liferay.portal.model.UserNotificationDeliveryConstants.TYPE_WEBSITE}</type>
<default>true</default>
<modifiable>true</modifiable>
</delivery-type>
</definition>
</user-notification-definitions>
|
So in our example portlet class we can actually add a new
notification for the user. We can do it by using
UserNotificationEventLocalServiceUtil in either our service builder class or
one of our portlet classes.
Here’s how to add notification event: In below we are adding
a new employee data to employee persistence and so we are adding an event
saying that new employee has added to the site users. So we have to send this
notification event to all the site users by adding notification events to all.
employee
=EmployeeLocalServiceUtil.addEmployee(employee);
ServiceContext
serviceContext = new
ServiceContext();
serviceContext.setScopeGroupId(themeDisplay.getScopeGroupId());
JSONObject payloadJSON =
JSONFactoryUtil.createJSONObject();
payloadJSON.put("userId", themeDisplay.getUserId());
payloadJSON.put("employeeId", employee.getEmpId());
payloadJSON.put("additionalData", "Your
notification was added!");
List<User> siteUsers= UserLocalServiceUtil.getGroupUsers(themeDisplay.getScopeGroupId());
for(User siteUser : siteUsers){
UserNotificationEventLocalServiceUtil.addUserNotificationEvent(siteUser.getUserId(),
com.example.notifications.ExampleUserNotificationHandler.PORTLET_ID, new
Date().getTime(), themeDisplay.getUserId(), payloadJSON.toString(), false, serviceContext);
System.out.println("notification
event adding to user : "+siteUser.getScreenName());
}
|
So now that we have our notification inside the database we
want to actually show it to the user. When we look at the dockbar our
notification number gets increased so we can be pretty sure that the
notification was added. When you attempt to actually look at the notification
you will probably see a blank white box. We need the notification handler class
to actually handle the display side of our notification. This current example
also handles the behavior like providing Approve and Reject buttons right in our
example notification so that our example user could perform an action straight
from the dockbar notification.
Here is the class : ExampleUserNotificationHandler.java
package
com.example.notifications;
import
com.liferay.portal.kernel.json.JSONFactoryUtil;
import
com.liferay.portal.kernel.json.JSONObject;
import
com.liferay.portal.kernel.notifications.BaseUserNotificationHandler;
import
com.liferay.portal.kernel.portlet.LiferayPortletResponse;
import
com.liferay.portal.kernel.util.StringBundler;
import
com.liferay.portal.kernel.util.StringUtil;
import
com.liferay.portal.model.UserNotificationEvent;
import
com.liferay.portal.service.ServiceContext;
import
javax.portlet.ActionRequest;
import
javax.portlet.PortletURL;
import
javax.portlet.WindowState;
public class
ExampleUserNotificationHandler extends
BaseUserNotificationHandler{
public static final String PORTLET_ID = "testexample_WAR_testexampleportlet";
public
ExampleUserNotificationHandler() {
setPortletId(ExampleUserNotificationHandler.PORTLET_ID);
}
@Override
protected String
getBody(UserNotificationEvent userNotificationEvent,
ServiceContext serviceContext) throws Exception {
JSONObject jsonObject=
JSONFactoryUtil.createJSONObject(userNotificationEvent.getPayload());
long employeeId = jsonObject.getLong("employeeId");
String title = "A new
Employee data has been added ";
String bodyText = "";
LiferayPortletResponse liferayPortletResponse = serviceContext.getLiferayPortletResponse();
PortletURL confirmURL = liferayPortletResponse.createActionURL(com.example.notifications.ExampleUserNotificationHandler.PORTLET_ID);
confirmURL.setParameter(ActionRequest.ACTION_NAME, "doSomethingGood");
confirmURL.setParameter("redirect", serviceContext.getLayoutFullURL());
confirmURL.setParameter("employeeId", String.valueOf(employeeId));
confirmURL.setParameter("userNotificationEventId", String.valueOf(userNotificationEvent.getUserNotificationEventId()));
confirmURL.setWindowState(WindowState.NORMAL);
PortletURL ignoreURL = liferayPortletResponse.createActionURL(com.example.notifications.ExampleUserNotificationHandler.PORTLET_ID);
ignoreURL.setParameter(ActionRequest.ACTION_NAME, "cancelForExample");
ignoreURL.setParameter("redirect", serviceContext.getLayoutFullURL());
ignoreURL.setParameter("employeeId", String.valueOf(employeeId));
ignoreURL.setParameter("userNotificationEventId", String.valueOf(userNotificationEvent.getUserNotificationEventId()));
ignoreURL.setWindowState(WindowState.NORMAL);
String body = StringUtil.replace(getBodyTemplate(),
new String[] {
"[$CONFIRM$]", "[$CONFIRM_URL$]", "[$IGNORE$]",
"[$IGNORE_URL$]", "[$TITLE$]", "[$BODY_TEXT$]" }, new String[] {
serviceContext.translate("approve"), confirmURL.toString(),
serviceContext.translate("reject"), ignoreURL.toString(),
title, bodyText });
return body;
}
@Override
protected String
getLink(UserNotificationEvent userNotificationEvent,
ServiceContext serviceContext) throws Exception {
JSONObject jsonObject=
JSONFactoryUtil.createJSONObject(userNotificationEvent.getPayload());
long employeeId = jsonObject.getLong("employeeId");
LiferayPortletResponse liferayPortletResponse = serviceContext.getLiferayPortletResponse();
PortletURL confirmURL = liferayPortletResponse.createRenderURL(com.example.notifications.ExampleUserNotificationHandler.PORTLET_ID);
confirmURL.setParameter("redirect", serviceContext.getLayoutFullURL());
confirmURL.setParameter("employeeId", String.valueOf(employeeId));
confirmURL.setParameter("userNotificationEventId", String.valueOf(userNotificationEvent.getUserNotificationEventId()));
confirmURL.setWindowState(WindowState.NORMAL);
return confirmURL.toString();
}
protected String
getBodyTemplate() throws Exception {
StringBundler sb = new
StringBundler(5);
sb.append("<div
class=\"title\">[$TITLE$]</div><div ");
sb.append("class=\"body\">[$BODY_TEXT$]<a
class=\"btn btn-action ");
sb.append("btn-success\"
href=\"[$CONFIRM_URL$]\">[$CONFIRM$]</a>");
sb.append("<a
class=\"btn btn-action btn-warning\" href=\"");
sb.append("[$IGNORE_URL$]\">[$IGNORE$]</a></div>");
return sb.toString();
}
}
|
com.example.notifications.ExampleUserNotificationHandler.PORTLET_ID
string that you use as your notification type has to match an actual portlet ID.
So I have passed the PORTLET_ID as “testexample_WAR_testexampleportlet”
which was the portelt I am placing notifications.
Now our code works as like If any employee data is added in
to the table a new notification will send to all site users and that
notification will be displayed on the notification bar .
After adding new employee a notification will be displayed
in the dock bar as given below:
We can see the notification number is increased in the above
screen. Click on notification:
As we created the content “A new Employee data has been
added with 2 buttons ‘Approve’ and ‘Reject’ is displaying on notification title
and body. Once clicking on ‘Approve’ button means the notification has read by
the user and decreases its count. And all the notifications will be available in the “Notifications” portlet
which was the market place portlet .
For approve and reject buttons the code we should write in
our portlet controller class as given below: TestExample.java
package com.test.example;
import com.liferay.counter.service.CounterLocalServiceUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.json.JSONObject;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.model.User;
import com.liferay.portal.service.ServiceContext;
import com.liferay.portal.service.UserLocalServiceUtil;
import
com.liferay.portal.service.UserNotificationEventLocalServiceUtil;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.testexample.model.Employee;
import com.liferay.testexample.service.EmployeeLocalServiceUtil;
import com.liferay.util.bridges.mvc.MVCPortlet;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
public class TestExample extends MVCPortlet {
public void
addEntity(ActionRequest request, ActionResponse response)
throws
Exception {
ThemeDisplay
themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
Employee
employee =
EmployeeLocalServiceUtil.createEmployee(CounterLocalServiceUtil.increment(Employee.class.getName()));
SimpleDateFormat
sdf = new SimpleDateFormat("MM/dd/yyyy");
employee.setFirstName(ParamUtil.getString(request,
"firstName"));
employee.setFullName(ParamUtil.getString(request,
"fullName"));
employee.setAge(ParamUtil.getInteger(request,
"age"));
employee.setJoinedDate(ParamUtil.getDate(request,
"joinedDate", sdf));
employee.setGender(ParamUtil.getString(request,
"gender"));
employee.setCompanyId(themeDisplay.getCompanyId());
employee.setGroupId(themeDisplay.getScopeGroupId());
employee.setUserId(themeDisplay.getUserId());
employee
=EmployeeLocalServiceUtil.addEmployee(employee);
ServiceContext
serviceContext = new ServiceContext();
serviceContext.setScopeGroupId(themeDisplay.getScopeGroupId());
JSONObject
payloadJSON = JSONFactoryUtil.createJSONObject();
payloadJSON.put("userId",
themeDisplay.getUserId());
payloadJSON.put("employeeId",
employee.getEmpId());
payloadJSON.put("additionalData", "Your notification
was added!");
List<User> siteUsers=
UserLocalServiceUtil.getGroupUsers(themeDisplay.getScopeGroupId());
for(User siteUser : siteUsers){
UserNotificationEventLocalServiceUtil.addUserNotificationEvent(siteUser.getUserId(),
com.example.notifications.ExampleUserNotificationHandler.PORTLET_ID, new
Date().getTime(), themeDisplay.getUserId(), payloadJSON.toString(), false,
serviceContext);
System.out.println("notification
event adding to user : "+siteUser.getScreenName());
}
response.setRenderParameter("mvcPath","/html/testexample/view.jsp");
}
public void
doSomethingGood(ActionRequest request, ActionResponse response)
throws
IOException, PortletException {
ThemeDisplay
themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
long
groupId = themeDisplay.getScopeGroupId();
long
employeeId = ParamUtil.getLong(request, "employeeId");
long
userNotificationEventId = ParamUtil.getLong(request,
"userNotificationEventId");
try
{
UserNotificationEventLocalServiceUtil.deleteUserNotificationEvent(userNotificationEventId);
}
catch (PortalException e) {
System.out.println("Failed
to remove notification:"+e.getMessage());
}
catch (SystemException e) {
System.out.println("Failed
to remove notification:"+e.getMessage());
}
}
public void
cancelForExample(ActionRequest request, ActionResponse response)
throws
IOException, PortletException {
ThemeDisplay
themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
long
groupId = themeDisplay.getScopeGroupId();
long
employeeId = ParamUtil.getLong(request, "employeeId");
long
userNotificationEventId = ParamUtil.getLong(request,
"userNotificationEventId");
try
{
UserNotificationEventLocalServiceUtil.deleteUserNotificationEvent(userNotificationEventId);
}
catch (PortalException e) {
System.out.println("Failed
to remove notification:"+e.getMessage());
}
catch (SystemException e) {
System.out.println("Failed
to remove notification:"+e.getMessage());
}
}
}
|
No comments:
Post a Comment