In my attempt to develop an interactive chat web application using Java EE 7, I am specifically utilizing JSF 2.2 with ajax.
The concept involves having a slow pending asynchronous ajax request waiting on the server for each unique client. When a new message is received by the server, all pending requests are triggered, causing messages to be displayed in all clients. Once the requests are completed, new ones are sent out by the clients. If no message arrives within 30 seconds, the request is returned for submission of a new one before the previous request times out.
I have managed to implement this functionality as shown below:
index.xhtml:
<?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.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>async jsf app</title>
<h:outputScript library="js" name="resendscript.js" />
</h:head>
<h:body>
async jsf app
<h:form id="jsfappform">
say something:
<h:inputText id="newmsg" value="#{jsfAsync.newMessage}" />
<h:commandButton id="sendbut" value="say" action="#{jsfAsync.say}" />
<br /><br />
Messages:
<br /><br />
<h:outputText id="msgs" value="#{jsfAsync.msgs}" escape="false">
<h:outputScript>resendRequest()</h:outputScript>
</h:outputText>
<h:commandButton id="reloadbut" value="" action="#{jsfAsync.resend}" style="visibility: hidden">
<f:ajax execute="@this" render="msgs" onevent="handleAjax" onerror="handleError" />
</h:commandButton>
<h:commandButton id="clearbut" value="clear" action="#{jsfAsync.clear}" />
<h:outputScript>resendRequest()</h:outputScript>
</h:form>
</h:body>
</html>
resendscript.js:
function handleAjax(data)
{
var status = data.status;
switch(status)
{
case "success": resendRequest();
break;
}
}
function handleError(data) { }
function resendRequest()
{
document.getElementById("jsfappform:reloadbut").click();
}
backing bean JsfAsync.java:
package jsfasync;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ApplicationScoped;
@ManagedBean
@ApplicationScoped
public class JsfAsync
{
private final List<String> messages;
private final Object wakeup;
public JsfAsync()
{
wakeup = new Object();
messages = new ArrayList<String>();
}
public void setNewMessage(String msg)
{
synchronized(messages) { messages.add(msg); }
}
public void say()
{
synchronized(wakeup) { wakeup.notifyAll(); }
}
public void resend()
{
try {
synchronized(wakeup) { wakeup.wait(30000); }
} catch (Exception e) { }
}
public void clear()
{
synchronized(messages) { messages.clear(); }
say();
}
public String getNewMessage() { return ""; }
public String getMsgs()
{
StringBuilder msgs = new StringBuilder();
synchronized(messages)
{
for (String m : messages)
{
msgs.append(m);
msgs.append("<br />");
}
return msgs.toString();
}
}
}
My intention is to update the body of the resendRequest() javascript function with the ajax request API in the following manner:
jsf.ajax.request('jsfappform:reloadbut', null,
{'javax.faces.behavior.event': 'action',
'execute': 'jsfappform:reloadbut',
'render': 'jsfappform:msgs',
'onevent': 'handleAjax',
'onerror': 'handleError'});
However, it seems that despite successfully performing the ajax request call, the onevent parameter was disregarded and the event handler did not execute upon completion of the request. Do you have any advice on how to address this issue?