JSF2 composite component with PrimeFaces

Exclusive offer: get 50% off this eBook here
Instant PrimeFaces Starter [Instant]

Instant PrimeFaces Starter [Instant] — Save 50%

Design and develop awesome web user interfaces for desktop and mobile devices with PrimeFaces and JSF2 using practical, hands-on examples with this book and ebook

$14.99    $7.50
by Ian Hlavats | July 2013 | Open Source Web Development

This article created by Ian Hlavats, the author of Instant PrimeFaces Starter [Instant], will help provide you with all the information that you need to get up to speed with JSF2 composite component with PrimeFaces and chat feature with PrimeFaces Push. It will also teach you to open a WebSocket communication channel, the use of PrimeFaces socket component, and the implementation of chat rooms for web browsers.

(For more resources related to this topic, see here.)

The Contacts tab is where users can connect with their friends, family, and colleagues and chat online. For this screen let's write a JSF2 composite component that can render any list of User objects for desktop and mobile browsers.

In preceding screenshot, we use a JSF2 composite component to render groups of contacts for the user. When a contact has signed in, his or her avatar image is highlighted to show presence. Clicking on a contact opens a live chat dialog that showcases the PrimeFaces Push technology.

We enable our JSF2 composite component to be integrated in a mobile UI based on PrimeFaces Mobile. In this mode, our component renders a simpler, mobile-friendly UI with some special CSS and JavaScript to leverage the PrimeFaces Mobile API.

Our contactList composite component has three attributes:

  • header: Specifies the text to be displayed above the contacts
  • value: Binds the component to any list of Userobjects
  • mobile: Set to true for mobile display mode

We can use our <mycompany:contactList> tag to display a list of friends, family, and colleagues. Notice that we use the PrimeFaces poll component to check every 10 seconds to see if one of our contacts has logged in.

<h:form id="contactsForm">
<p:poll update="contactsPanel" interval="10" />...
<p:accordionPanel id="contactsPanel" multiple="true">
<p:tab title="Friends">
<mycompany:contactList header="Friends"
value="#{contactsController.friends}" />

</p:tab>
...
</p:accordionPanel>
</h:form>

Let's see how we developed this component. First we declared the composite component's interface:

<composite:interface>
<composite:attribute name="value" required="true" />
<composite:attribute name="header" required="false"
default="People" />
<composite:attribute name="mobile" required="false"
default="false" />
</composite:interface>

Next, we implement the composite component using the PrimeFaces carousel component for desktop, and the simpler PrimeFaces dataList component for mobile. Notice that we use the boolean mobile attribute declared in our component interface in our rendering logic by using the #{cc.attrs.mobile} EL expression. If the mobile attribute is true, we render the mobile UI, otherwise we show the desktop UI.

<composite:implementation>
<p:carousel style="width:100%" value="#{cc.attrs.value}"
var="person" numVisible="4"
rendered="#{not empty cc.attrs.value and not
cc.attrs.mobile}"
itemStyleClass="person-item">
<f:facet name="header">
<h:outputText value="#{cc.attrs.header}" />
</f:facet>
<h:panelGrid columns="1" style="width:100%">
<p:commandLink value="Chat"
onclick="chatDialogWidget.show()"
update=":chatForm:chatPanel"
actionListener="#{chatController.beginChat}"
disabled="#{!userController.isUserPresent(person)}" />
<h:outputText value="#{person.firstName}" />
<p:graphicImage value="#{resource['images:user-icon.png']}"
width="75"
rendered="#{userController.isUserPresent(person)}" />
<p:graphicImage value="#{resource['images:offline-user-
icon.png']}"width="75"
rendered="#{!userController.isUserPresent(person)}" />
</h:panelGrid>
<f:facet name="footer">
<h:outputText value="Total: #{cc.attrs.value.size()}" />
</f:facet>
</p:carousel>
<!-- Mobile UI -->

<p:dataList style="width:110%" value="#{cc.attrs.value}"
var="person" id="mobileContactList"
rendered="#{not empty cc.attrs.value and
cc.attrs.mobile}"
itemStyleClass="mobile-person-item">
<f:attribute name="filter" value="true" />
<h:panelGroup
rendered="#{userController.isUserPresent(person)}">
<h:outputLink value="#chat" onclick="beginMobileChat()">
<p:graphicImage
value="#{resource['images:user-icon.png']}"
width="50"
style="text-align:left; vertical-align:middle;
margin-top:15px" />
<h:outputText value="#{person.firstName}"
style="display:block; margin-top:18px;
font-size:0.9em" />
</h:outputLink>
</h:panelGroup>
<h:panelGroup
rendered="#{!userController.isUserPresent(person)}">
<p:graphicImage value="#{resource['images:offline-user-
icon.png']}" width="50"
style="text-align:left; vertical-align:middle;
margin-top:15px" />
<h:outputText value="#{person.firstName}"
style="display:block; margin-top:18px;
font-size:0.9em" />
</h:panelGroup>
</p:dataList>
</composite:implementation>

Chat feature with PrimeFaces Push

One of the most interesting features of PrimeFaces is the Prime Push API. Designed by Atmosphere Framework creator Jean-François Arcand, the Prime Push API supports asynchronous communication from the web server to the web browser on desktop or mobile using various transports such as WebSocket and Comet.

Prime Push technology opens up a whole new set of possibilities for web developers. We will implement a simple chat feature for our web application based on Prime Push.

What is WebSocket?

WebSocket is a standardized, full-duplex communication protocol based on TCP that can be used to establish a persistent, bidirectional communication channel between a web browser and a web server. WebSocket has better performance than Comet techniques such as long polling and HTTP streaming, and is well supported by modern browsers and application servers.

WebSocket support can be enabled in GlassFish 3 with a simple command:

$GLASSFISH_HOME/bin/asadmin set configs.config.server-config.network-
config.protocols.protocol.http-listener-1.http.websockets-support-
enabled=true

Once WebSocket support is enabled in GlassFish, we are ready to use Prime Push in our web application.

Chat room

Before we can see the power of Prime Push in action, we need to implement a chat room feature in our application. The PrimeFaces showcase application includes a chat room example, so we have adapted it for our purposes and integrated it into our application.

One of the coolest things about PrimeFaces is the ability to push updates to desktop and mobile users at the same time from the server using PrimeFaces Mobile and Prime Push technologies. The previous screenshot shows a live chat session in our web application between a mobile and desktop user.

Getting started with Prime Push

The first step in using Prime Push is configuring the Prime Push servlet in web.xml:

<servlet>
<servlet-name>PushServlet</servlet-name>
<servlet-class>org.primefaces.push.PushServlet</servlet-cla
<init-param>
<param-name>org.primefaces.push.rules</param-name>
<param-value>com.mycompany.websocket.DefaultPushRule</param
value>
</init-param>
...
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>PushServlet</servlet-name>
<url-pattern>/primepush/*</url-pattern>
</servlet-mapping>

An important point about this configuration is the use of a custom push rule implemented in the com.mycompany.websocket.DefaultPushRule class. This class provides some GlassFish-specific support that was necessary to ensure Prime Push worked properly on GlassFish.

Opening a WebSocket communication channel

The next step in using Prime Push is to establish the WebSocket communication channel between the web page and the web server. In our application, when the user clicks on the Chat link on the contact screen, we call the following method in our ChatController using Ajax to begin the chat:

public void beginChat() {
User user = userController.getUser();
RequestContext requestContext =
RequestContext.getCurrentInstance();
// ...
requestContext.execute("socketWidget.connect(
'/" + user.getUsername() + "')");
pushContext.push(CHANNEL + "*", user.getUsername() +
" joined the channel.");
}

Notice that we use the very cool PrimeFaces RequestContext API to invoke some JavaScript in the browser when the response is completed. We can do a lot more with the RequestContext API, such as update a DOM element, scroll to a component, and execute arbitrary JavaScript. Definitely check it out. Here we call connect() to tell the browser to listen for messages on the WebSocket communication channel.

Use of a PrimeFaces socket component

The PrimeFaces socket component establishes a WebSocket connection with the PushServlet running in our web application. Here it uses a communication channel named /chat for sending and receiving Push messages.

p:socket onMessage="handleMessage" channel="/chat"
autoConnect="false"
widgetVar="socketWidget" />
<script type="text/javascript">
//<![CDATA[
function handleMessage(data) {
// append chat messages to output panel
var chatContent = $(PrimeFaces.escapeClientId('chatForm:chatPanel'));
chatContent.append(data + '<br />');
//keep scroll
chatContent.scrollTop(chatContent.height());
}
//]]>
</script>

When a chat message is received, our handleMessage() JavaScript function is called and the chat message is appended to the chat content panel.

Implementation of the chat room dialog for desktop web browsers

To provide a chat room user interface for desktop users, we implemented the following modal dialog using the PrimeFaces dialog component. It renders the list of active users on our website.

<p:dialog header="Chat" modal="true" showEffect="fade"
hideEffect="fade" widgetVar="chatDialogWidget" width="700"
position="center" appendToBody="false" height="400" draggable="true"
resizable="false"id="chatDialog">
...
<p:outputPanel id="chatPanel" layout="block"
styleClass="ui-corner-all ui-widget-content chatlogs"/>
<p:dataList id="users" var="user" value="#{activeUsers}"

styleClass="usersList">
<f:facet name="header"> Users</f:facet>
#{user.username}
</p:dataList>

Next, we need to provide an input field for users to enter a chat message.

<p:inputText value="#{chatController.globalMessage}"
styleClass="messageInput" style="width:300px" />
<p:spacer width="5" />
<p:commandButton value="Send"
actionListener="#{chatController.sendGlobal}"
oncomplete="$('.messageInput').val('').focus()"/>
...
<p:commandButton value="Close" style="margin-top:20px"
actionListener="#{chatController.endChat}"
onclick="chatDialogWidget.hide()"
global="false" />

When the user clicks on the Send button, the chat message text is submitted using Ajax and our ChatController.sendGlobal() method is invoked to push the message to the WebSocket channel.

private static final String CHANNEL = "/chat/";
public void sendGlobal() {
String username = getLoggedInUser().getUsername();
pushContext.push(CHANNEL + "*", username + ": " + globalMessage);
}

On the client side, the browser will receive the message over the WebSocket channel and our handleMessage() JavaScript function will append the text to the chat panel.

Summary

This article helped you understand JSF2 composite component with PrimeFaces and chat feature with PrimeFaces Push. It also helped you understand about opening a WebSocket communication channel, use of PrimeFaces socket component, and implementation of chat rooms for web browsers.

Resources for Article:


Further resources on this subject:


Instant PrimeFaces Starter [Instant] Design and develop awesome web user interfaces for desktop and mobile devices with PrimeFaces and JSF2 using practical, hands-on examples with this book and ebook
Published: June 2013
eBook Price: $14.99
See more
Select your format and quantity:

About the Author :


Ian Hlavats

Ian Hlavats is an experienced Java developer, instructor, speaker, and author of the book JSF 1.2 Components (Packt). He has worked for clients in government, insurance, and entertainment industries, writing Java applications using Swing, Struts, JSF2, PrimeFaces, jQuery, and other UI technologies. He has delivered Java courses in college and corporate training environments including a one-year engagement with Cognos/IBM.

He is on the JSF 2.2 Expert Group and contributed to the next generation of the JSF specification. A regular speaker at Java EE conferences, he has given presentations on JSF and PrimeFaces technologies since 2008 at JSF Summit, NFJS, and JAXConf in San Francisco. He is the creator of JSFToolbox for Dreamweaver, a suite of design and coding extensions for JSF developers. He co-hosts a podcast on JSF and Java EE technologies with fellow authors Kito D. Mann and Daniel Hinojosa. He holds a Bachelor of Humanities degree from Carleton University and IT certificates from Algonquin College.

Books From Packt


Java EE 6 Development with NetBeans 7
Java EE 6 Development with NetBeans 7

PrimeFaces Cookbook
PrimeFaces Cookbook

JSF 2.0 Cookbook
JSF 2.0 Cookbook

Java EE 5 Development using GlassFish Application Server
Java EE 5 Development using GlassFish Application Server

JSF 1.2 Components
JSF 1.2 Components

Java EE 6 with GlassFish 3 Application Server
Java EE 6 with GlassFish 3 Application Server

Java EE 5 Development with NetBeans 6
Java EE 5 Development with NetBeans 6

JBoss RichFaces 3.3
JBoss RichFaces 3.3


Your rating: None Average: 1.3 (3 votes)

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
d
r
z
M
6
v
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software