tags:

views:

89

answers:

4

Hello,

I have a web-application where the users can be sent directly to some specific pages (such as a page where he can view or edit an item). To achieve that, we provide a specific url. These urls are located outside the current web-application (i.e. they can be present in another web-application, or in an email).

The url looks like http://myserver/my-app/forward.jsf?action=XXX&param=YYY, where:

  • action represents the page where the user will be redirected. You can consider this as the from-outcome of any JSF action in navigation-case in faces-config.xml.
  • actionParam is a parameter for the previous action (generally an item ID)

So for example, I can have these kind of urls:

  • http://myserver/my-app/forward.jsf?action=viewItem&actionParam=1234
  • http://myserver/my-app/forward.jsf?action=editItem&actionParam=1234

Of course, I have a Java class (bean) that will check some security constraints (i.e. is the user allowed to see / edit the corresponding item?) and then redirect the user to the correct page (such as edit.xhtml, view.xhtml or access-denied.xhtml).


Current implementation

Currently, we have a basic way to accomplish the forward. When the user clicks on the link, the following XHTML page is called:

<html>
    <body id="forwardForm">
        <h:inputHidden id="myAction" binding="#{forwardBean.hiddenAction}"/>
        <h:inputHidden id="myParam" binding="#{forwardBean.hiddenActionParam}"/>
        <h:commandButton id="forwardBtn" actionListener="#{forwardBean.doForward}" style="display: none;"/>
    </body>
    <script type="text/javascript">
        document.getElementById('forwardForm:forwardBtn').click();
    </script>
</html>

As you can see, I bind two <h:inputHidden> components in my Java bean. They will be used to store the value of both action and actionParam request parameter (using FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("actiontParam");). I also provide the doForward method that which will be called immediately when the page is rendered, which will redirect (again) the user to the real page. The method is:

public void doForward(ActionEvent evt) {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    String redirect = // define the navigation rule that must be used in order to redirect the user to the adequate page...
    NavigationHandler myNav = facesContext.getApplication().getNavigationHandler();
    myNav.handleNavigation(facesContext, null, redirect);
}

This solution is working, but I have two problems with that:

  • I don't like the way it is implemented. I'm sure that I can have something simplier (using a Servlet?).
  • This solution is using Javascript, and I must not use Javascript (as this forward may be used by old Blackberry users, where the Javascript is not supported).

So my question is how to refactor this redirection / forward feature?

Technical information

Java 1.6, JSF 1.2, Facelets, Richfaces

A: 

you should use action instead of actionListener:

<h:commandLink id="close" action="#{bean.close}" value="Close" immediate="true" 
                                   />

and in close method you right something like:

public String close() {
   return "index?faces-redirect=true";
}

where index is one of your pages(index.xhtml)

Of course, all this staff should be written in our original page, not in the intermediate. And inside the close() method you can use the parameters to dinamically choose where to redirect.

Vladimir Ivanov
Using `action` or `actionListener` has absolutely no impact on my current problem.
romaintaz
And the OP is using JSF 1.x, not 2.x. Also, the redirect will cause request parameters to be lost.
BalusC
A: 
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse();
response.sendRedirect("somePage.jsp");
ycnix
Doesn't answer my question. Where do you want me to put this code? And how can it be called without any user interaction nor Javascript call?
romaintaz