Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSF commandLink, POSTing and the back button

I've recently started doing some JSF work - before that I've always used PHP or Python for web development.

I was somewhat surprised to find that JSF uses HTTP POSTs to navigate when the h:commandLink tag is used.

I have been using the commandLink as this is apparently the correct way to build JSF apps. Why does JSF use POST for navigation? What's wrong with GET? I can only assume that the Javascript that is automatically generated by JSF for the onclick events could exceed the maximum length for a GET request.

I already have a number of pages that are navigated using h:commandLink. This works wells until I use the browser's back button. How should I go about handling the back button in JSF?

I'm struggling to understand why JSF was build around the POST. It breaks bookmarking, back-paging and the ability to have your page indexed in search engines.

like image 371
Steve Claridge Avatar asked Aug 04 '09 13:08

Steve Claridge


3 Answers

It isn't going to help you build a link on the client, but be aware of outputLink.

There is a redirect element for navigation rules which can help for some refresh issues.

<navigation-rule>
  <display-name>navBack</display-name>
  <from-view-id>/navBack.jsp</from-view-id>
  <navigation-case>
    <from-outcome>navTo</from-outcome>
    <to-view-id>/navTo.jsp</to-view-id>
    <redirect />
  </navigation-case>
</navigation-rule>

If all else fails, you can do the redirect URL yourself, as in this action:

public String doAction() {
  System.out.println("Did some non-idempotent operation");
  FacesContext context = FacesContext.getCurrentInstance();
  ExternalContext extContext = context.getExternalContext();
  Application app = context.getApplication();
  ViewHandler viewHandler = app.getViewHandler();
  String url = viewHandler.getActionURL(context, "/navTo.jsp");
  url = url + (url.indexOf('?') < 0 ? '?' : '+') + "foo=bar";
  url = extContext.encodeResourceURL(url);
  try {
    extContext.redirect(url);
  } catch (IOException e) {
    throw new FacesException(e);
  }
  return null;
}

Caveats: I can't remember if I'm encoding the URL correctly.

Various 3rd party libraries add differing gluts of features. I'm not sure if anything has been done in JSF 2.0 in this area, but it might be worth a look.

like image 72
McDowell Avatar answered Nov 14 '22 10:11

McDowell


Yup. JSF is built around POST and it's one of the biggest sticking points about JSF. Take a look at the JAX-RS/Seam or Spring for bookmarkable GETable pages.

like image 41
Drew Avatar answered Nov 14 '22 08:11

Drew


As BalusC said on his blog, GET should be used for navigation between page. Use h:outputLink for navigation.

You can read his PostRedirectGetListener and it will solve back/refresh form resubmission confirmation message.

I advice you to add the following to beforePhase in order to handle partial ajax processing (if relevant):

if(event.getFacesContext().getPartialViewContext().isAjaxRequest())
{
    return;
}
like image 1
Daniel Avatar answered Nov 14 '22 10:11

Daniel