Sunday, March 13, 2011

JSF 2 Internals - Efficient way of Redirecting to a Page

There are certain cases where you are needed to redirect  to a different page than requested by user e.g. if user has requested a secure page for which he/she is not authorized, your application will have to redirect to login page or some other page. I have created a utility method to redirect to a page. You can call anywhere but for example given above, you can call it a beforePhase method of RestoreViewPhaseListener. Here is the method code:

public static void redirect(String viewId) {

execute(FacesContext.getCurrentInstance(), viewId);
}


private static void execute(FacesContext facesContext, String viewId)
throws FacesException {

UIViewRoot viewRoot = null;
ViewDeclarationLanguage vdl = facesContext.getApplication()
.getViewHandler()
.getViewDeclarationLanguage(facesContext, viewId);

if (vdl != null) {
// If we have one, get the ViewMetadata...
ViewMetadata metadata = vdl.getViewMetadata(facesContext,
viewId);

if (metadata != null) { // perhaps it's not supported
// and use it to create the ViewRoot. This will have, at
// most
// the UIViewRoot and its metadata facet.
viewRoot = metadata.createMetadataView(facesContext);

}
}

facesContext.setViewRoot(viewRoot);
facesContext.renderResponse();
assert (null != viewRoot);

}

viewId is the name of page to which it should redirect e.g. "/redirect.xml" (assuming page is at root level). Inside execute method, you get the ViewDeclarationLanguage which is page type specific e.g. if page is in facelet markup, you get DefaultFaceletViewDeclarationLanguage and if page is in JSP markup, then you will get corresponding ViewDeclarationLanguage. After this, page root tree is constructed by calling createMetadataView if it is not already constructed. Finally set the new ViewRoot and call renderResponse method, which will bypass all phases and will jump directly to render phase.

3 comments:

vortex said...

hey, thanks for the post, being a newby i have a hard time understand what to do with the code you provided, i'm learning jsf, and i need a redirect when a user is accessing a page that he shouldn't, can you help me with that (using the boolean property isConnected in a managed bean UserBean ) where do i have to copy your code and how can i use it ? i need to provide a tag with this logic , right ? thanks and sorry for bothering you

amer sohail said...

First of all copied my code in some of ur utility class. If you don't have it then create a class and copied that code to it.

Then you will have to register PhaseListener for "RestoreView" phase and inside beforePhase method, you can write code something like this,

FacesContext context = event.getFacesContext(); String requestPath = context.getExternalContext().getRequestPathInfo();
if (requestPath != null && requestPath.equals("/your_page.xhtml")){
FacesUtil.redirect("/redirected_page.xhtml");

In the code "your_page" is the page against which you want to redirect. "redirected_page" is the page to which you want to redirect. "FacesUtil" is my utility class which contains my code given in this blog.

waladabacallao said...

Gambling in Las Vegas - Mapyro
The Strip's most popular slot machines and 파주 출장샵 gambling machines are called table games 울산광역 출장샵 (also called 동해 출장샵 video poker and video poker). You can 동해 출장마사지 bet on 거제 출장안마 either the