Growl kind of message notifications in ZK Framework

In this post, I am trying to share an implementation to get Growl kind of message notifications in ZK based application.

In summary, Idea is to have JQuery for notifications and make javascript calls from java code in ZK.

I chose jquery plug-in developed by Eric from his blog here

Steps:
1)  Download jquery and plugin available here

2) Include plugin in .zul file. I kept this in my template file header area of application

<style src="/resources/css/ui.notify.css"/>
<script type="text/javascript" src="/resources/js/jquery-1.7.1.js"></script>
<script type="text/javascript" src="/resources/js/jquery.ui.widget.js"></script>
<script type="text/javascript" src="/resources/js/jquery.notify.js"></script>

3) Create two div tags, one for regular notifications and one for error messages in zul file.
Note: I added only two containers here. One for success messages and another one for both warning and error message. You can create as many as you want to display messages in different styles.

<h:div id="<strong>container</strong>" style="height: 0px;">
...
</h:div>
<h:div id="<strong>errorContainer</strong>" style="height: 0px;">
..
</h:div>

4) Added code to call notify() method on page load (as explained for jquery)

<script type="text/javascript" <strong>defer="true"</strong>>
jQuery("#container").notify();
jQuery("#errorContainer").notify();
</script>

5) Added below javascript code to one of js files

/* Growl message display methods */
function displayNotificationMessage(messageTitle, message) {
jQuery("#container").notify();
jQuery("#container").notify("create", 0, {
title: messageTitle,
text: message
});
}

function displayErrorMessage(messageTitle, message) {
jQuery("#errorContainer").notify();
jQuery("#errorContainer").notify("create", "error-msg-template", {
title: messageTitle,
text: message
});
}

6) Created below java class to call above javascript methods –

This class’s interface exposes below methods –

public void displayNotificationMessage(String summary, String detail); //Displays notification message
public void displayWarningMessage(String summary, String detail); //Displays warning message
public void displayErrorMessage(String summary, String detail); //Displays error message
public void addNotificationMessage(String summary, String detail); //Adds a notification message to session
public void addWarningMessage(String summary, String detail); //Adds a warning message to session
public void addErrorMessage(String summary, String detail); //Adds a error message to session
public void displayPendingMessages(); //Displays all messages stored in session and clean them up.

Implementaiton

import org.zkoss.zk.ui.Executions;

import org.zkoss.zk.ui.util.Clients;

import java.util.ArrayList;
import java.util.List;

/**
* JQuery based grawl message display handler.
*
* @author Anil
*/
public class GrowlJQMessageHandler implements MessageHandler {

@Override
public void displayNotificationMessage(String summary, String detail) {
Clients.evalJavaScript("displayNotificationMessage('" + summary + "', '" + detail + "')");
}

@Override
public void displayWarningMessage(String summary, String detail) {
Clients.evalJavaScript("displayErrorMessage('" + summary + "', '" + detail + "')");
}

@Override
public void displayErrorMessage(String summary, String detail) {
Clients.evalJavaScript("displayErrorMessage('" + summary + "', '" + detail + "')");
}

@Override
public void addNotificationMessage(String summary, String detail) {
ZKMessage message = new ZKMessage(ZKMessage.INFO_MSG, summary, detail);
addMessage(message);
}

@Override
public void addWarningMessage(String summary, String detail) {
ZKMessage message = new ZKMessage(ZKMessage.WARNING_MSG, summary, detail);
addMessage(message);
}

@Override
public void addErrorMessage(String summary, String detail) {
ZKMessage message = new ZKMessage(ZKMessage.ERROR_MSG, summary, detail);
addMessage(message);
}

@Override
public void displayPendingMessages() {
List zkMessages = (List) Executions.getCurrent().getSession().getAttribute(SkillSessionScopeKey.PENDING_MESSAGE_LIST.getValue());
if(zkMessages != null) {
for (ZKMessage message : zkMessages) {
if (message.getSeverity() == ZKMessage.INFO_MSG) {
displayNotificationMessage(message.getSummary(), message.getDetails());
} else if (message.getSeverity() == ZKMessage.WARNING_MSG) {
displayWarningMessage(message.getSummary(), message.getDetails());
} else if (message.getSeverity() == ZKMessage.ERROR_MSG) {
displayErrorMessage(message.getSummary(), message.getDetails());
}
}
zkMessages.clear();
Executions.getCurrent().getSession().setAttribute(SkillSessionScopeKey.PENDING_MESSAGE_LIST.getValue(), zkMessages);
}
}

private void addMessage(ZKMessage message) {
List zkMessages = null;
if (Executions.getCurrent().getSession().getAttribute(SkillSessionScopeKey.PENDING_MESSAGE_LIST.getValue()) != null) {
zkMessages = (List) Executions.getCurrent().getSession().getAttribute(SkillSessionScopeKey.PENDING_MESSAGE_LIST.getValue());
zkMessages.add(message);
} else {
zkMessages = new ArrayList();
zkMessages.add(message);
}
Executions.getCurrent().getSession().setAttribute(SkillSessionScopeKey.PENDING_MESSAGE_LIST.getValue(), zkMessages);
}
}

Usage:

Below code can be called from one of the composite right after particular action

1) To display success message immediately after the action (On same page) –

messageHandler.displayNotificationMessage("Success", "Session cancelled successfully!!!");

2) To display warning message immediately after the action (On same page) –

messageHandler.displayWarningMessage("Invalid Session ID", "Session ID entry is invalid, Please try again");

3) To display success message in redirected page after the action (On redirected page) –

messageHandler.addNotificationMessage("Success", "Session cancelled successfully!!!");

Below are screen shots of success and warning messages

Hope this post helps!!!

ZK validator to check user id uniqueness on registration

I wrote a very simple validator to verify the uniqueness of user entered id by checking against database. It also validates if the user id is more than 5 characters long.

import org.apache.commons.lang.StringUtils;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zul.Constraint;
import User;
import UserService;
/**
* ZK validator for user id uniqueness.
*
* @author Anil
*/
public class UserIdUniquenessValidator implements Constraint {
/** user service to pull user info from DB */
private UserService userService;
public void validate(Component comp, Object value) throws WrongValueException {
if (value == null || StringUtils.isEmpty((String) value)) {
throw new WrongValueException(comp, “Please enter User ID”);
}
if (((String)value).trim().length() < 4) {
throw new WrongValueException(comp, “User Id must be at least 5 characters”);
}
User user = userService.load((String) value);
if (user != null) {
throw new WrongValueException(comp, “User ID already exists”);
}
}
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
}
I declared this validator as spring bean in spring context file:
<bean id=”userIdUniquenessValidator” class=”com.gavs.skill.ui.validator.UserIdUniquenessValidator”>
<property name=”userService” ref=”userService”/>
</bean>
ZUL file:
<bean id=”userIdUniquenessValidator” class=”UserIdUniquenessValidator”>
<property name=”userService” ref=”userService”/>
</bean>
<?variable-resolver class=”org.zkoss.zkplus.spring.DelegatingVariableResolver”?>
<grid>
<columns>
<column label=””></column>
<column label=””></column>
</columns>
<rows>
<row>
<label value=”First Name” width=”150px” />
<textbox  id=”indFirstName” width=”150px” constraint=”no empty”  value=”@{user.firstName}” />
</row>
<row>
<label value=”Last Name” width=”150px” />
<textbox id=”indLastName” width=”150px” constraint=”no empty” value=”@{user.lastName}”/>
</row>
<row>
<label value=”Email” width=”150px” />
<textbox id=”indEmail” width=”150px” constraint=”/.+@.+\.[a-z]+/: Please enter an e-mail address” value=”@{user.emailId}”/>
</row>
<row>
<label value=”User Id” width=”150px” />
<textbox id=”indUserId” width=”150px” constraint=”${userIdUniquenessValidator}” value=”@{user.userId}”/>
</row>
<row>
<label value=”Password” width=”150px” />
<textbox id=”password” type=”password”  width=”150px” constraint=”no empty” value=”@{user.password}”/>
</row>
</rows>
</grid>
.….
Thats all. On blur of user id field, validator validates the user entered info  and display the error message if user id already exist in database.
Posted in ZK. Tags: , . 1 Comment »

Custom resolver to explose logged in user info for ZK (Spring Security)

To expose spring security’s authentication info with object name “authentication” in ZK CE, the following simple resolver is useful.

import org.springframework.security.context.SecurityContextHolder;
import org.zkoss.xel.VariableResolver;
/**
* Resolver to make “authentication” object available for zk EL.
*
* @author Anil
*
*/
public class SecurityResolver implements VariableResolver {
public Object resolveVariable(String name) {
if (“authentication”.equals(name)) {
return SecurityContextHolder.getContext().getAuthentication();
}
return null;
}
}

This is resolver will be used as below:

<?variable-resolver class=”com.gavs.zk.common.SecurityResolver”?>

<toolbar id=”toolbar” style=”margin-top: -15px;”>

<toolbarbutton image=”/images/icons/small/home.ico” label=”Home”   if=”${authentication.principal == ‘roleAnonymous’}” style=”font-size: 11px; font-weight: bold;”>

<attribute name=”onClick”>

<![CDATA[Executions.sendRedirect(“/index.zul”); ]]>

</attribute>

</toolbarbutton>

</toolbar>

Here  “Home” link gets displayed only if user has not yet logged into system.

Spring Security custom tag in ZK community edition

I upgraded my app to ZK 5.x community edition from 3.x and realized that spring security tags support not provided by community edition. I have created a custom tag to enforce restrictions based on roles in zul page.  I thought of sharing it here:

1) Create a class with static function to verify the role from spring’s  SecurityContextHolder.

public class SpringSecurityUserAccessSupport {
private static final Logger LOG = LoggerFactory.getLogger(SpringSecurityUserAccessSupport.class);
/**
* Verifies whether logged in user is in passed in role.
*
* @param role
* @return
*/
public static boolean isUserInRole(String roleStr) {
String[] roles = StringUtils.split(roleStr, “,”);
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
GrantedAuthority[] authorities = auth.getAuthorities();
Role role;
for (int i = 0; i < roles.length; i++) {
role = new Role(StringUtils.trimToEmpty(roles[i]));
if (ArrayUtils.contains(authorities, role)) {
return true;
}
}
return false;
}
}

2) create  a new .tld file and config.xml file under metainfo\tld directory

custom.tld:

<taglib>

<uri>http://www.domain.com/custom</uri&gt;

<function>

<name>isUserInRole</name>

<function-class>SpringSecurityUserAccessSupport</function-class>

<function-signature>boolean isUserInRole(java.lang.String)</function-signature>

</function>

</taglib>

config.xml:

<?xml version=”1.0″ encoding=”UTF-8″?>

<config>

<taglib>

<taglib-uri>http://www.domain.com/custom</taglib-uri&gt;

<taglib-location>metainfo/tld/custom.tld</taglib-location>

</taglib>

</config>

3) Use the tag inside .zul file

<?taglib uri=”http://www.domain.com/custom&#8221; prefix=”sec”?>

<hbox width=”100%” align=”center”>

<toolbar id=”toolbar” style=”margin-top: -15px;”>

<toolbarbutton image=”/images/icons/small/home.ico” label=”Add User” if=”${sec:isUserInRole(‘ROLE_INDIVIDUAL_USER’) }” style=”font-size: 11px; font-weight: bold;”>

<attribute name=”onClick”>

<![CDATA[Executions.sendRedirect(“/index.zul”); ]]>

</attribute>

</toolbarbutton>

</toolbar>

</hbox>

Here I am displaying “Add User” option on toolbar only when logged in user has role “ROLE_INDIVIDUAL_USER“.