Every wanted to access a JSF view by directly entering the view onto URL? This is a common request. In my case, I needed to link to specific places in my JSF app from a legacy non-JSF application. This is the type of thing you'd think would be straightforward, but JSF falls flat.
I scoured the web for solutions to this, and this is the simplest: implement a phase listener. In the interest of getting right to it, here it is:
public class RedirectPhaseListener implements PhaseListener {
public RedirectPhaseListener() {
}
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
public void afterPhase(PhaseEvent phaseEvent) {
}
public void beforePhase(PhaseEvent phaseEvent) {
FacesContext ctx = phaseEvent.getFacesContext();
HttpServletRequest request =
(HttpServletRequest) ctx.getExternalContext().getRequest();
String viewId = request.getParameter("viewId");
if (viewId != null) {
UIViewRoot page = ctx.getApplication().getViewHandler().createView(ctx, viewId);
ctx.setViewRoot(page);
ctx.renderResponse();
}
}
}
The phase listener gets the request, and checks for a parameter. The parameter is the path to the view ID you want to visit. For example: /faces/someview.xhtml. With Facelets, these goto URLs end up looking funny, because the real view ID is in the URL also,
/faces/home.xhtml?viewId=/faces/other.xhtml
Not nice, but it works. Other solutions I've seen try to get fancy by keeping a mapping a view+action result=new view. That's cleaner, and it's easy to do once you understand what's going on above.
