I am trying with Primefaces chat example here http://www.primefaces.org/showcase/push/chat.xhtml. But I am stuck here. I type in some messages and click send but OnMessage() was not called. I am using WebSphere 8.0, Primefaces 5.2, Primefaces Extension 3.2.0, Atmosphere 2.3.4. I saw this in the console.
chat.xhtmlWebSocket connection to 'ws://192.168.1.124:9080/BelsizeWeb/primepush/%7Broom%7D?X-Atmosphere-tracking-id=0&X-Atmosphere-Framework=2.2.9-javascript&X-Atmosphere-Transport=websocket&X-Atmosphere-TrackMessageSize=true&X-atmo-protocol=true' failed: Error during WebSocket handshake: Unexpected response code: 501
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//Dtd XHTML 1.0 Transitional//EN" "http://www.w3.org/tr/xhtml1/Dtd/xhtml1-transitional.dtd">
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:hx="http://www.ibm.com/jsf/html_extended">
<h:head>
<title>Welcome</title>
<meta http-equiv="keywords" content="enter,your,keywords,here" />
<meta http-equiv="description" content="A short description of this page." />
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link type="text/css" rel="stylesheet"
href="#{request.contextPath}/theme/primefaces-aristo/theme.css" title="default"/>
<script type="text/javascript" src="#{request.contextPath}/styleswitch.js"></script>
<link rel="SHORTCUT ICON" href="theme/csl.ico" id="index" />
<script src="../../scripting.js"></script>
<f:loadBundle basename="messages.MessageResources" var="msg" />
</h:head>
<h:body>
<p:growl id="growl" showDetail="true" />
<h:form id="form">
<p:remoteCommand name="updateList" update="users" process="@this" />
<p:fieldset id="container" legend="PrimeChat" toggleable="true">
<h:panelGroup rendered="#{chatView.loggedIn}">
<h:panelGrid columns="2" columnClasses="publicColumn,usersColumn" style="width:100%">
<p:outputPanel id="public" layout="block" styleClass="ui-corner-all ui-widget-content chatlogs" />
<p:dataList id="users" var="user" value="#{chatUsers.users}" styleClass="usersList">
<f:facet name="header">
Users
</f:facet>
<p:commandButton title="Chat" icon="ui-icon-comment" oncomplete="PF('pChat').show()" update=":form:privateChatContainer">
<f:setPropertyActionListener value="#{user}" target="#{chatView.privateUser}" />
</p:commandButton>
#{user}
</p:dataList>
</h:panelGrid>
<p:separator />
<p:inputText value="#{chatView.globalMessage}" styleClass="messageInput" />
<p:spacer width="5" />
<p:commandButton value="Send" actionListener="#{chatView.sendGlobal}" oncomplete="$('.messageInput').val('').focus()" />
<p:spacer width="5" />
<p:commandButton value="Disconnect" actionListener="#{chatView.disconnect}" global="false" update="container" />
</h:panelGroup>
<h:panelGroup rendered="#{not chatView.loggedIn}" >
Username: <p:inputText value="#{chatView.username}" />
<p:spacer width="5" />
<p:commandButton value="Login" actionListener="#{chatView.login}" update="container"
icon="ui-icon-person" />
</h:panelGroup>
</p:fieldset>
<p:dialog widgetVar="pChat" header="Private Chat" modal="true" showEffect="fade" hideEffect="fade">
<h:panelGrid id="privateChatContainer" columns="2" columnClasses="vtop,vtop">
<p:outputLabel for="pChatInput" value="To: #{chatView.privateUser}" />
<p:inputTextarea id="pChatInput" value="#{chatView.privateMessage}" rows="5" cols="30" />
<p:spacer />
<p:commandButton value="Send" actionListener="#{chatView.sendPrivate}" oncomplete="PF('pChat').hide()" />
</h:panelGrid>
</p:dialog>
</h:form>
<p:socket onMessage="handleMessage" channel="/{room}" autoConnect="true" widgetVar="subscriber" />
<script type="text/javascript">
function handleMessage(message) {
var chatContent = $(PrimeFaces.escapeClientId('form:public')),
text = (message.user) ? message.user + ':' + message.text: message.text;
console.log(chatContent);
chatContent.append(text + '<br />');
//keep scroll
chatContent.scrollTop(chatContent.height());
if(message.updateList) {
updateList();
}
}
</script>
</h:body>
</html>
Code: Select all
package pagecode;
import java.io.Serializable;
import org.primefaces.context.RequestContext;
import org.primefaces.push.EventBus;
import org.primefaces.push.EventBusFactory;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
@ManagedBean(name = "chatView")
@SessionScoped
public class ChatView implements Serializable {
//private final PushContext pushContext = PushContextFactory.getDefault().getPushContext();
// private final EventBus eventBus = EventBusFactory.getDefault().eventBus();
@ManagedProperty("#{chatUsers}")
private ChatUsers users;
private String privateMessage;
private String globalMessage;
private String username;
private boolean loggedIn;
private String privateUser;
private final static String CHANNEL = "/{room}/";
public ChatUsers getUsers() {
return users;
}
public void setUsers(ChatUsers users) {
this.users = users;
}
public String getPrivateUser() {
return privateUser;
}
public void setPrivateUser(String privateUser) {
this.privateUser = privateUser;
}
public String getGlobalMessage() {
return globalMessage;
}
public void setGlobalMessage(String globalMessage) {
this.globalMessage = globalMessage;
}
public String getPrivateMessage() {
return privateMessage;
}
public void setPrivateMessage(String privateMessage) {
this.privateMessage = privateMessage;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public boolean isLoggedIn() {
return loggedIn;
}
public void setLoggedIn(boolean loggedIn) {
this.loggedIn = loggedIn;
}
public void sendGlobal() {
EventBus eventBus = EventBusFactory.getDefault().eventBus();
eventBus.publish(CHANNEL + "*", username + ": " + globalMessage);
globalMessage = null;
}
public void sendPrivate() {
EventBus eventBus = EventBusFactory.getDefault().eventBus();
eventBus.publish(CHANNEL + privateUser, "[PM] " + username + ": " + privateMessage);
privateMessage = null;
}
public void login() {
RequestContext requestContext = RequestContext.getCurrentInstance();
if(users.contains(username)) {
loggedIn = false;
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Username taken", "Try with another username."));
requestContext.update("growl");
}
else {
users.add(username);
requestContext.execute("PF('subscriber').connect('/" + username + "')");
loggedIn = true;
}
}
public void disconnect() {
//remove user and update ui
users.remove(username);
RequestContext.getCurrentInstance().update("form:users");
//push leave information
EventBus eventBus = EventBusFactory.getDefault().eventBus();
eventBus.publish(CHANNEL + "*", username + " left the channel.");
//reset state
loggedIn = false;
username = null;
}
}
ChatUsers.java
Code: Select all
package pagecode;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
@ManagedBean(name = "chatUsers")
@ApplicationScoped
public class ChatUsers implements Serializable {
private List<String> users;
@PostConstruct
public void init() {
users = new ArrayList<String>();
}
public List<String> getUsers() {
return users;
}
public void remove(String user) {
this.users.remove(user);
}
public void add(String user) {
this.users.add(user);
}
public boolean contains(String user) {
return this.users.contains(user);
}
}
ChatResource.java
Code: Select all
package pagecode;
import org.primefaces.push.EventBus;
import org.primefaces.push.RemoteEndpoint;
import org.primefaces.push.annotation.OnClose;
import org.primefaces.push.annotation.OnMessage;
import org.primefaces.push.annotation.OnOpen;
import org.primefaces.push.annotation.PathParam;
import org.primefaces.push.annotation.PushEndpoint;
import org.primefaces.push.annotation.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.servlet.ServletContext;
@PushEndpoint("/{room}/{user}")
@Singleton
public class ChatResource {
private final Logger logger = LoggerFactory.getLogger(ChatResource.class);
@PathParam("room")
private String room;
@PathParam("user")
private String username;
@Inject
private ServletContext ctx;
@OnOpen
public void onOpen(RemoteEndpoint r, EventBus eventBus) {
logger.info("OnOpen {}", r);
eventBus.publish(room + "/*", new Message(String.format("%s has entered the room '%s'", username, room), true));
}
@OnClose
public void onClose(RemoteEndpoint r, EventBus eventBus) {
ChatUsers users= (ChatUsers) ctx.getAttribute("chatUsers");
users.remove(username);
eventBus.publish(room + "/*", new Message(String.format("%s has left the room", username), true));
}
@OnMessage(decoders = {MessageDecoder.class}, encoders = {MessageEncoder.class})
public Message onMessage(Message message) {
return message;
}
}
Message.java
Code: Select all
package pagecode;
public class Message {
private String text;
private String user;
private boolean updateList;
public Message() {
}
public Message(String text) {
this.text = text;
}
public Message(String text, boolean updateList) {
this.text = text;
this.updateList = updateList;
}
public Message(String user, String text, boolean updateList) {
this.text = text;
this.user = user;
this.updateList = updateList;
}
public String getText() {
return text;
}
public Message setText(String text) {
this.text = text;
return this;
}
public String getUser() {
return user;
}
public Message setUser(String user) {
this.user = user;
return this;
}
public boolean isUpdateList() {
return updateList;
}
public void setUpdateList(boolean updateList) {
this.updateList = updateList;
}
}
MessageDecoder.java
Code: Select all
package pagecode;
import org.primefaces.push.Decoder;
/**
* A Simple {@link org.primefaces.push.Decoder} that decode a String into a {@link Message} object.
*/
public class MessageDecoder implements Decoder<String,Message> {
//@Override
public Message decode(String s) {
String[] userAndMessage = s.split(":");
if (userAndMessage.length >= 2) {
return new Message().setUser(userAndMessage[0]).setText(userAndMessage[1]);
}
else {
return new Message(s);
}
}
}
MessageEncoder.java
Code: Select all
package pagecode;
import org.primefaces.json.JSONObject;
import org.primefaces.push.Encoder;
/**
* A Simple {@link org.primefaces.push.Encoder} that decode a {@link Message} into a simple JSON object.
*/
public final class MessageEncoder implements Encoder<Message, String> {
//@Override
public String encode(Message message) {
return new JSONObject(message).toString();
}
}
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>BelsizeWeb</display-name>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>primefaces.SUBMIT</param-name>
<param-value>partial</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<welcome-file-list>
<welcome-file>abcd.xhtml</welcome-file>
</welcome-file-list>
<filter>
<description>Redirect unauthenticated session to login page.</description>
<display-name>RedirectLogin</display-name>
<filter-name>RedirectLogin</filter-name>
<filter-class>com.belsize.servlet.filter.RedirectLogin</filter-class>
<init-param>
<param-name>login_page</param-name>
<param-value>/faces/login.xhtml</param-value>
</init-param>
<init-param>
<param-name>message_page</param-name>
<param-value>/faces/messages.xhtml</param-value>
</init-param>
<init-param>
<param-name>report_page</param-name>
<param-value>/faces/module/reports/rpt1000.xhtml</param-value>
</init-param>
<init-param>
<param-name>module_page</param-name>
<param-value>/faces/index.xhtml</param-value>
</init-param>
<init-param>
<param-name>warning_page</param-name>
<param-value>/faces/warning.xhtml</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>RedirectLogin</filter-name>
<url-pattern>/RedirectLogin</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>RedirectLogin</filter-name>
<url-pattern>*.xhtml</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>RedirectLogin</filter-name>
<url-pattern>/TestServlet</url-pattern>
</filter-mapping>
<!-- FACES -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<!-- PUSH -->
<servlet>
<servlet-name>Push Servlet</servlet-name>
<servlet-class>org.primefaces.push.PushServlet</servlet-class>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>Push Servlet</servlet-name>
<url-pattern>/primepush/*</url-pattern>
</servlet-mapping>
<!-- FILE UPLOAD -->
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<!-- MIME MAPPING -->
<mime-mapping>
<extension>ico</extension>
<mime-type>image/x-icon</mime-type>
</mime-mapping>
<!-- Session Expired -->
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/faces/login.xhtml</location>
</error-page>
</web-app>