Performing a JSF GET
»From the java and programming part of the brain.
According to several JSF forum posts (here and here), A JSF GET is not something a developer can convienently do.
In fact, it is a recommendation that all form submissions are done via the POST method. Well, over the past 3 months, I have adored JSF too much to allow this one lacking feature to get in the way of practical and simple use cases.
So here’s how I did a JSF GET:
- Create the link to an URL which maps to a filter
- Use the ServletRequest to fetch the link’s arguments.
- Using those arguments, create a backing bean of the appropriate state and put it in the HttpSession.
- Create and update the FacesContext object
- Forward the user to the correct JSP/JSF (UIView) page
You’ll need to construct a link in your JSP/JSF page. You can do it by hard coding an actual link, but in this example I’ve chose to do construct my link using the JSF HTML taglibs:
<h:outputLink id="x" value="jsf.get">
<f:verbatim>Some Link</f:verbatim>
<f:param name="editItem" value="00004"/>
</h:outputLink>
This will emit the following link in your JSP/JSF page.
http://localhost/context/jsf.get?editKey=00004
Now we add a filter to listen to requests for “jsf.get”:
<filter>
<filter-name>JSFGet Filter</filter-name>
<filter-class>com.JSFGet</filter-class>
</filter>
<filter-mapping>
<filter-name>JSFGet Filter</filter-name>
<url-pattern>*.get</url-pattern>
</filter-mapping>
Now, you need a filter that handles incoming GET requests properly. Included below is a stripped down version. I hope this bit of code will help anyone trying to accommodate GET requests with JSF.
import com.SuperBean;
import java.io.IOException;
public class JSFGet implements Filter {
private FilterConfig filterConf;
private ServletContext servletContext;
public void init(FilterConfig filterConfig)
throws ServletException {
this.filterConf = filterConfig;
this.servletContext = filterConfig.getServletContext();
}
public void doFilter(ServletRequest req,
ServletResponse res,
FilterChain fc)
throws IOException, ServletException {
FacesContext facesContext = getFacesContext(req, res);
req.getRequestDispatcher(facesContext.getViewRoot().getViewId()).
forward(req, res);
}
public void destroy() {
this.filterConf = null;
this.servletContext = null;
}
/**
FacesContext.setFacesContextAsCurrentInstance method is
protected.
*/
private abstract static class ProtectedFacesContext
extends FacesContext {
protected static void setFacesContextAsCurrentInstance(
FacesContext facesContext) {
FacesContext.setCurrentInstance(facesContext);
}
}
/** Here's where the Filter/JSF integration takes place. */
private FacesContext getFacesContext(ServletRequest req,
ServletResponse res) {
/** Try to get it first */
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext != null)
return facesContext;
// Use the FactoryFinder to grab the Lifecycle object
FacesContextFactory contextFactory = (FacesContextFactory)
FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
LifecycleFactory lifecycleFactory = (LifecycleFactory)
FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
Lifecycle lifecycle =
lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
// Put my Bean into HttpSession
HttpServletRequest httpReq = (HttpServletRequest) req;
HttpSession httpSess = httpReq.getSession();
SuperBean editor = new SuperBean();
String key = req.getParameter("editKey");
editor.setEditKey(key);
// If your loadSomething method requires a FacesContext object,
// call it after it has been constructed
editor.loadSomething();
httpSess.setAttribute("SuperBean", editor);
// Here's where the ProtectedFacesContext comes in.
facesContext = contextFactory.
getFacesContext(servletContext, req, res, lifecycle);
ProtectedFacesContext.setFacesContextAsCurrentInstance(facesContext);
// Create a new ViewRoot. Default behavior returns null
UIViewRoot view = facesContext.getApplication().
getViewHandler().createView(facesContext,"edit.jsf");
facesContext.setViewRoot(view);
// Call loadSomething(FacesContext)
// editor.loadSomething(facesContext);
return facesContext;
}
}