By Student

2013-03-20 10:51:13 8 Comments

I am currently learning JSF and was rather amazed and puzzled when I realized that whenever we use <h:form>, the standard behavior of JSF is to always show me the URL of the previous page in the browser, as opposed to the URL of the current page.

I understand that this has to do with the way JSF always posts a form to the same page and then just renders whatever page the controller gives it back to the browser which doesn't know the page location has changed.

It seems like JSF has been around for long enough that there must be a clean, solid way to deal with this. If so, would you mind sharing?

I have found various workarounds, but sadly nothing that seems like a real solid solution.

  • Simply accept that the URL is misleading.
  • Append "?faces-redirect=true" to the return value of every bean's action and then
    • figure out how to replace @RequestScoped with something else (Flash Scopes, CDI conversation, @SessionScoped, ...).
    • accept to have two HTTP round trips for every user action.
  • Use some method (e.g. 3rd party library or custom code) to hide the page name in the URL, always using the same generic URL for every page.

If "?faces-redirect=true" is as good as it gets, is there a way do configure an entire application to treat all requests this way?


@BalusC 2013-03-20 12:05:48

Indeed, JSF as being a form based application targeted MVC framework submits the POST form to the very same URL as where the page with the <h:form> is been requested form. You can confirm it by looking at the <form action> URL of the generated HTML output. This is in web development terms characterized as postback. A navigation on a postback does by default not cause a new request to the new URL, but instead loads the target page as content of the response. This is indeed confusing when you merely want page-to-page navigation.

Generally, the right approach as to navigation/redirection depends on the business requirements and the idempotence (read: "bookmarkability") of the request (note: for concrete code examples, see the "See also" links below).

  • If the request is idempotent, just use a GET form/link instead of POST form (i.e. use <a>, <form>, <h:link> or <h:button> instead of <h:form> and <h:commandXxx>).
    For example, page-to-page navigation, Google-like search form, etc.

  • If the request is non-idempotent, just show results conditionally in the same view (i.e. return null or void from action method and make use of e.g. <h:message(s)> and/or rendered).
    For example, in-page data entry/edit, multi-step wizard, modal dialog, confirmation form, etc.

  • If the request is non-idempotent, but the target page is idempotent, just send a redirect after POST (i.e. return outcome with ?faces-redirect=true from action method, or manually invoke ExternalContext#redirect(), or put <redirect/> in legacy XML navigation case).
    For example, showing list of all data after successful editing, redirect after login, etc.

Note that pure page-to-page navigation is usually idempotent and this is where many JSF starters fail by abusing command links/buttons for that and then complain afterwards that URLs don't change. Also note that navigation cases are very rarely used in real world applications which are developed with respect to SEO/UX and this is where many JSF tutorials fail by letting the readers believe otherwise.

Also note that using POST is absolutely not "more secure" than GET because the request parameters aren't immediately visible in URL. They are still visible in HTTP request body and still manipulatable. So there's absolutely no reason to prefer POST for idempotent requests for the sake of "security". The real security is in using HTTPS instead of HTTP and checking in business service methods if currently logged-in user is allowed to query entity X, or to manipulate entity X, etc. A decent security framework offers annotations for this.

See also:

@Student 2013-03-20 12:25:58

thanks for that very systematic answer. You mention a lot of options I wasn't aware of. I'll have a look at them. multi-step wizard was in deed what I was thinking of. Do you happen to know a page with a good example on how to do that on a single page without using 3rd party tools?

@BalusC 2013-03-20 12:28:15

@Student 2013-03-20 12:33:36

that's very cool. The individual pages/steps remain inaccessible for the user? I especially like that you can use @ViewScoped with that. thanks!

@Robbie62 2014-12-05 00:56:56

Please excuse my ignorance BalusC (yet again). Why did the designers of JSF not use the URL stored for the browser's back button to know where to send the POST back rather than mess with the browser's URL. No doubt there is a technical reason for it, but this is the only thing that really annoys me about JSF. It screws up: CSS file locations when coming out of a sub-folder; bookmarks; and also container security, as it will happily display a secure page, because the container security is looking at the current URL, and seeing the previous page, not the actual current supposedly secured page.

@BalusC 2014-12-05 07:52:56

As answered, just don't use POST for page-to-page navigation.

@alibttb 2018-08-03 09:31:57

@BalusC what about saving a form in details page and returning to the list page?

@BalusC 2018-08-03 14:43:00

@alibttb: saving a form is non-idempotent and viewing a list is certainly idempotent.

@alibttb 2018-08-03 16:07:42

True but this details page is idempotent and it has a Save button, now I have another <p:button value="Close" outcome="list.xhtml"/> just to go to the list and keep it bookmarkable, I'd like to have a Save&Close button

@BalusC 2018-08-05 13:56:46

@alibttb: I think you haven't read the answer from top to bottom.

@alibttb 2018-08-06 08:30:09

I actually read it but it's a little confusing, I'll give it more effort @BalusC

@BalusC 2018-08-06 13:46:08

@alibttb: In your example, the request is non-idempotent and the target page is idempotent. That matches the 3rd item of the navigation approaches.

@alibttb 2018-08-11 19:49:55

@BalusC this is true, I just wanted to avoid ?faces-redirect=true in every action method return value, what is the <redirct/> tage you mentioned.

@Harshal_Kalavadiya 2018-08-23 14:58:47

Hi @BalusC I have one JSF application where URL is getting change for all pages but there is one specific page, If I will navigate to other page from that specific page then URL is not getting changed. Can you guide me on this?

@BalusC 2018-08-24 15:37:54

@Harshal_Kalavadiya: as answered, just perform a redirect instead of a forward.

Related Questions

Sponsored Content

18 Answered Questions

[SOLVED] How do I modify the URL without reloading the page?

32 Answered Questions

15 Answered Questions

[SOLVED] How to change the URI (URL) for a remote Git repository?

  • 2010-03-12 12:48:47
  • e-satis
  • 1352253 View
  • 3391 Score
  • 15 Answer
  • Tags:   git url git-remote

20 Answered Questions

[SOLVED] Get the current URL with JavaScript?

  • 2009-06-23 19:26:45
  • dougoftheabaci
  • 2674178 View
  • 2838 Score
  • 20 Answer
  • Tags:   javascript url

31 Answered Questions

[SOLVED] How do I make a redirect in PHP?

  • 2009-04-20 14:13:22
  • Sam
  • 2645084 View
  • 1180 Score
  • 31 Answer
  • Tags:   php redirect

30 Answered Questions

[SOLVED] Get current URL with jQuery?

33 Answered Questions

[SOLVED] How do I get the current absolute URL in Ruby on Rails?

3 Answered Questions

[SOLVED] How to get the browser to navigate to URL in JavaScript

2 Answered Questions

How can i make requestscope available for more than one request in jsf?

  • 2012-10-19 19:54:18
  • techtabu
  • 937 View
  • 0 Score
  • 2 Answer
  • Tags:   java jsp jsf

3 Answered Questions

[SOLVED] JSF CDI Bean initialization on every page access

  • 2010-11-22 08:38:25
  • bertie
  • 1807 View
  • 1 Score
  • 3 Answer
  • Tags:   jsf jsf-2

Sponsored Content