JSF with Ajax, Phase Listener vs Servlet Comparison
December 30, 2005 27 Comments
When I first heard about Ajax, I thought the asynchronous call to the server can be handled by a servlet in a jsf application.At first sight the servlet idea was the only one that came up to my mind and I saw several examples that uses a servlet to embed ajax in jsf. After a while, I’ve observed another method to use AJAX with JSF; “phaselistener”. I’ve decided to write the same application with these techniques seperately in order to figure out the possible pros and cons of both. The example is simple, redirecting the request to response, the user clicks a button and an ajax request is sent to the server side.The response is sent back to the client as a string defining the technique being used and the string message is displayed in a simple textfield.
Here is the important part of the jsf page; A textfield to display the response and a button to send the request. The sndReq javascript function takes the technique name as an argument like ‘PhaseListener’ or ‘Servlet’;
<inputText id=”text1″></h:inputText>
<BUTTON onclick=”sndReq(‘Servlet or PhaseListener here’)”>Submit</BUTTON>
And here are the javascript functions to create the request and handle the response, the sending of the request is given seperately in the description of the techniques.
function createRequestObject() {
var ro;
var browser = navigator.appName;
if(browser == “Microsoft Internet Explorer”){
ro = new ActiveXObject(“Microsoft.XMLHTTP”);
}else{
ro = new XMLHttpRequest();
}
return ro;
}
var http = createRequestObject();
function handleResponse() {
if(http.readyState == 4){
var response = http.responseText;
document.getElementById(‘form1:text1’).value = response;
}
}
PhaseListener
Following is the javascript function to send the request to the server side.
function sndReq(requestString) {
http.open(‘get’, ‘PROJECTNAME/faces/technique-comparison?technique=’+requestString);
http.onreadystatechange = handleResponse;
http.send(null);
}
And the PhaseListener to handle the Ajax request.
public class AjaxListener implements PhaseListener {
private static final String AJAX_VIEW_ID = “technique-comparison”;
public void afterPhase(PhaseEvent event) {
String rootId = event.getFacesContext().getViewRoot().getViewId();
if (rootId.indexOf(AJAX_VIEW_ID) != -1)
handleAjaxRequest(event);
}
private void handleAjaxRequest(PhaseEvent event) {
FacesContext context = event.getFacesContext();
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
HttpServletRequest request = (HttpServletRequest)context.getExternalContext().getRequest();
String name = request.getParameter(“technique”);
try {
response.getWriter().write(name);
context.responseComplete();
}catch(Exception exception) {
exception.printStackTrace();
}
}
public void beforePhase(PhaseEvent arg0) {
}
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
}
The idea is exciting, when the request reaches the server, the phase listener takes the scene and after the restore view phase, it checks whether is an Ajax request or not. If it is, it creates a response and forces the life cycle to jump to the render response phase.
Servlet
Now the function is changed and the url target is a servlet;
function sndReq(requestString) {
http.open(‘get’, ‘/PROJECTNAME/servlet/ResponseServlet?technique=’+requestString);
http.onreadystatechange = handleResponse;
http.send(null);
}
And the handling servlet;
public class ResponseServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String technique = request.getParameter(“technique”);
response.getWriter().write(technique);
}
}
As you see, servlet code is much shorter than the PhaseListener and looks simpler however we should consider the simplicity of the example. Servlet does not need to understand whether it is an ajax request or not because it is the servlet’s only job, however the phase listener must catch an ajax request. On the other hand the phase listener is a native solution but the servlet is in the external context. This gives the advantage to accss the stuff in context of faces easier. Also if you are writing a custom component that uses external sources like javascript files or css, phaselisteners can serve these for you from a single jar file which also contains your code.
Since I am a phaselistener fan I would suggest to use the phaselistener method whenever you try to add some ajax magic to your jsf application.
There are plus sides to phase listeners, you do not need to have an extra entry in the web.xml thus you can bundle them in a jar and just drop them in as JSF component pack, JSF takes care of the rest.
However the main disadvantage is, that phase listeners follow a chain pattern and the entire chain is called at every request, while at servlet level the servlets are chosen upon pattern.
Ok it does not make too much of a difference, but a difference between a theoretical log(n) and a fixed n in the calling order. Practically both methods probably cause the same performance hit.
You cane much more with JSF, because it is a component framework.
This is my idea:
ajax:request define a req javascript function which send an ajax request to the PhaseListener, with “divId” as parameter. component.
ajax:request component decode the ajax request, and fire the action event.
The testBean.getList method can affect the
Now the the phaseListener start to play its role:
substitute the current writer with an xml writer, and render the target component (the div modified by the managed bean).
Now on the client side, the javascript function “req” handle the incoming xml and performa a DOM substitution of the div element, as described by the xml created by the phase listener.
sources attribute of “ajax:request” can be used to build post parameters throught javascript. So you can have a very good integration between JSF and ajax.
What do you think about this?
I tried your example. It works but why response get in client side always duplicated my message.
Say request msg “abc”, the return value from server is “abcabc”
But from output of server side, its okay
I was trying to get the Phase Listener working, but I can’t seem to figure out where or how you’re mapping PROJECTNAME/faces/technique-comparison to the Phase Listener. I configured the phase listener as follows in faces-config.xml:
My question is how does JSF know that “technique-comparison” is mapped to ComparisonPhaseListener? Do we have to specify the mapping in another file?
Thanks for the info.
Mapping is done programmatically;
private static final String AJAX_VIEW_ID = “technique-comparison”;
public void afterPhase(PhaseEvent event) {
String rootId = event.getFacesContext().getViewRoot().getViewId();
if (rootId.indexOf(AJAX_VIEW_ID) != -1)
handleAjaxRequest(event);
}
qrqrwr
I am running into the same problem that Anthony mentioned. The response is always duplicated. If the request message is “Phase”, the response text is “PhasePhase”. I noticed that afterPhase() and handleAjaxRequest() methods are called twice. What is fix for this problem.
But from output of server side, its okay
I found the solution for the problem at http://wiki.apache.org/myfaces/FAQ#Twice
The JSF specification requires any JSF implementation to automatically load /WEB-INF/faces-config.xml at startup. There is consequently no need for the following context parameter:
Putting this context parameter in your deployment descriptor will force any JSF implementation to load the configuration twice, therefore registering each phase listener twice.
Yes, this is a well known and common mistake. There is no need to declare the default config file in web.xml.
Hi,
I have the same problem. The response is always duplicated. I already deleted the declaration of the config file in my web.xml, but the response is still duplicated. Any idea?
Another question:
When I use a Servlet for this example, how must I map this in web.xml?
Because Faces-requests call the Faces-Servlet.
Thanks for your help!
gggg
ss
123
Hi Cagatay
Thanks for excellent article on http://www.jroller.com/page/cagataycivici?entry=jsf_with_ajax_phase_listener.
Wondering how this works as i implemented your example and getting Null Pointer Exception in handleAjaxRequest method . Here is the snippet
String name = request.getParameter(“technique”);
System.out.println(“Name=”+name); // This prints Null
try {
response.getWriter().write(name);
context.responseComplete();
}catch(Exception exception) {
exception.printStackTrace();
}
I can understand why its printing Null since the jsp page is not yet rendered and their is no request parameter yet. So in this case how your example works as the PhaseListener is always executed prior to rendering of jsp page and hence it always result in request parameter being NULL
Regards
Bansi
testing
JSF with Ajax
Please forgive my ignorance here… but how would this work if one’s Faces Servlet mapping is “*.jsf” instead of “/faces/*”?
The information in this post is *exactly* what I was looking for, since I’m trying to implement this type of Ajax call — but currently the project I’m working on has the Faces Servlet mapping set to “*.jsf”.
So I added another mapping for “/jsf/*”, like so:
…and here’s the updated javascript i’m using to call the phase listener:
function sndReq(requestString)
{
var url = “http://localhost:8080/ajaxphaselistener/jsf/technique-comparison?technique=” + requestString;
http.open(‘get’, url );
http.onreadystatechange = handleResponse;
http.send(null);
}
Unfortunately, I’m getting an error 404, which says: “The requested resource (/ajaxphaselistener/technique-comparison) is not available.”
Note that the “jsf” is missing from between ajaxphaselistener and technique-comparison. I don’t know if that’s significant or not, but I thought it was a bit strange – kind of like *something* was happening under the hood but maybe it was getting confused (perhaps due to the multiple Faces Servlet mappings?)
Anyway, any insights or comments about how to get this working will be greatly appreciated…
Thanks!
///eks
OK… Thanks to Jay’s post earlier in this thread, I figured out my problem by putting both parts together to form a complete solution.
I was missing the entry in my faces-config.xml to enable the phase listener (which I didn’t know I needed):
After putting this entry in my config file, it came to life! w00t!!!
Additionally, as a side note, I *am* using two mappings and it seems to be working fine (*.jsf and /jsf/*). Let me know if this is a bad idea or not… 🙂
Thanks again to Cagatay and Jay for their combined bits information which allowed me to solve this problem so quickly!!!
When I started to combine AJAX with my own JSF component I was sure that the encodeXXX() methods of UIInput class (in fact UIComponent) will be used to render an AJAX answer. And I’m surprise that I haven’t access to my component. It will be much simpler than rendering answer in PhaseListener.
Let’s consider an example. encodeBegin() method renders a table with header, body and footer. If I want to render new body (table rows) using AJAX (let’s say user wanted to use filer) I have to code body rendering in PhaseListener once again.
Am I right, or there is a possibility to use my component rendering methods?
evankstone, specification allows you to create as many mapping as you want, so I think it is correct.
The duplicate output can be avoided by using the conditional check on the phase id.
interesting thank you…
breast augmentation new york city san diego breast augmentation
very interesting
account forex online trading broker canada forex online
chewable valium
chewable valium
diet pill for extreme weight loss
diet pill for extreme weight loss
vegetarian diets for weight loss
vegetarian diets for weight loss
car rental italy
car rental italy
aw
aw