Semantics of "?faces-redirect=true" in <commandlink action=...> and why not use it everywhere - jsf

I would like to understand what are the semantics behind appending the "?faces-redirect=true" in the action property of a <h:commandlink> tag in JSF2.0. Whether with it or with out it, the application indeed navigates to the target page specified in the action. So at first glance it seems that the only effect is cosmetic, i.e. to provide feedback to the user (if he is looking at the browser's visited URL) that he has moved to a new page. But if it is so innocuous and side-effects-free I cannot see why it is not the default behaviour. I suspect that it has to do with the post-based mechanism of JSF2.0. I 've noticed when browsing through a JSF application that the URLs one sees at his browser (when ?faces-redirect=true is not used) are the ones of the "previous" "page".
meta-NB. I am behind a firewall and plagued with the "SO requires external JavaScript from another domain" issue so I apologize for the absence of formatting. I will also provide feedback on your answers in a few hours, when I can access from another domain.

Page-to-page navigation should not be performed using POST at all. You should be using normal <h:link> or <h:button> for this instead of <h:commandLink> or <h:commandButton>.
So instead of
<h:commandLink value="Next page" action=nextpage.xhtml?faces-redirect=true" />
you should actually be using
<h:link value="Next page" outcome="nextpage.xhtml" />
This has the major benefit that the website is now SEO friendly. Searchbots namely doesn't index forms.
Use the <h:commandLink> only if you need to submit a form with some user input. But more than often the result is just presented in the same page, if necesary conditionally rendered/included. Only on successful submits which absolutely needs to go to a different page (e.g. login/logout), you should indeed be sending a redirect. This is the so-called Post-Redirect-Get pattern.
See also
How to navigate in JSF? How to make URL reflect current page (and not previous one)
When should I use h:outputLink instead of h:commandLink?

Related

How to stop action delete when reload page in jsf [duplicate]

We're using JSF 2.0 on WebSphere v8.5 with several component libraries PrimeFaces 4.0, Tomahawk 2.0, RichFaces, etc.
I am looking for generic mechanism to avoid form re-submission when the page is refreshed, or when the submit button is clicked once again. I have many applications with different scenarios.
For now I have considered disabling the button with a piece of JavaScript in onclick attribute, but this is not satisfying. I'm looking for a pure Java implementation for this purpose, something like the Struts2 <s:token>.
I am looking for generic mechanism to avoid form re-submission when the page is refreshed
For that there are at least 2 solutions which can not be combined:
Perform a redirect after synchronous post. This way the refresh would only re-execute the redirected GET request instead of the initial request. Disadvantage: you can't make use of the request scope anymore to provide any feedback to the enduser. JSF 2.0 has solved this by offering the new flash scope. See also How to show faces message in the redirected page.
Perform the POST asynchronously in the background (using ajax). This way the refresh would only re-execute the initial GET request which opened the form. You only need to make sure that those forms are initially opened by a GET request only, i.e. you should never perform page-to-page navigation by POST (which is at its own already a bad design anyway). See also When should I use h:outputLink instead of h:commandLink?
or when the submit button is clicked once again
For that there are basically also at least 2 solutions, which could if necessary be combined:
Just block the enduser from being able to press the submit button during the submit and/or after successful submit. There are various ways for this, all depending on the concrete functional and design requirements. You can use JavaScript to disable the button during submit. You can use JSF's disabled or rendered attributes to disable or hide the button after submit. See also How to do double-click prevention in JSF 2. You can also use an overlay window during processing ajax requests to block any enduser interaction. PrimeFaces has <p:blockUI> for the purpose.
Validate uniqueness of the newly added entity in the server side. This is way much more robust if you absolutely want to avoid duplication for technical reasons rather than for functional reasons. It's fairly simple: put a UNIQUE constraint on the DB column in question. If this constraint is violated, then the DB (and DB interaction framework like JPA) will throw a constraint violation exception. This is best to be done in combination with a custom JSF validator which validates the input beforehand by performing a SELECT on exactly that column and checking if no record is returned. A JSF validator allows you to display the problem in flavor of a friendly faces message. See also among others Validate email format and uniqueness against DB.
Instead of creating a token manually, you can use BalusC' solution. He proposed a Post-Redirect-GET pattern in his blog
Alternative solutions can be found in these answers:
Simple flow management in Post-Redirect-Get pattern
How can Flash scope help in implementing the PostRedirectGet (PRG) pattern in JSF2.0
<!--Tag to show message given by bean class -->
<p:growl id="messages" />
<h:form>
<h:inputText a:placeholder="Enter Parent Organization Id" id="parent_org_id" value="#{orgMaster.parentOrganization}" requiredMessage="Parent org-id is required" />
<h:commandButton style="margin-bottom:8px;margin-top:5px;" class="btn btn-success btn-block " value="Save" type="submit" action="#{orgMaster.save}" onclick="resetform()" />
</h:form>
public String save() {
FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getFlash().setKeepMessages(true); //This keeps the message even on reloading of page
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Your submission is successful.", " ")); // To show the message on clicking of submit button
return "organizationMaster?faces-redirect=true"; // to reload the page with resetting of all fields of the form.. here my page name is organizationMaster...you can write the name of form whose firlds you want to reset on submission
}

Choosing how to pass parameters to a target bean/page using JSF

I have been using JSF for a few years now, but I still have doubts when it comes to deciding how to pass parameters to a target page/bean.
I do think this question is a bit complex, and that some may tell me to break it down into smaller questions. But, I also think that the answer to all of the questions bellow are related, and that it addresses the lack of intuitiveness when all you want JSF to do is: "Go to that page and pass this as a parameter".
First, how to decide between Forward and Redirect?
After that, how to choose between h:commandLink/h:commandButton, h:link or h:outputLink?
Then, combined with the option I choose above, should I use f:param or f:setPropertyActionListener? Will both properly pass parameters to the target bean, independently of its scope?
Finally, on the target bean/page, when should I use f:viewParam, or recover parameters from the request programmatically?
I'm going to answer your questions based on my own experience. Some of them are so open that more than one answer could fit.
A page forward is the way to go unless you explicitly require the browser url to be changed. A page forward is basically faster than a redirection as it requires less steps. A page redirect is required if you want to make your views bookmarkable.
Use <h:commandLink />/<h:commandButton /> only when you need to POST the server. Later on, you'll be able to perform a page forward or a redirection depending on what the method returns. As an example:
<h:commandLink action="#{bean.processForm}" value="Submit" />
public String processForm(){
try{
save();
return "list";
}
catch(Excepcion e){
addFacesMessage("Error saving");
//Error saving the object, keep in the same view
return null;
}
}
Use <h:link outcome="list" value="Go to list" /> for pure page to page navigation within the JSF application. You can use either page forward and redirect. Use <f:param /> to pass view parameters.
<h:outputLink value="www.stackoverflow.com" /> could be used for external links to other sites (not into your application). Use <f:param /> to pass view parameters. I however prefer to use plain HTML with <a href="www.stackoverflow.com" /> myself for this case.
As for passing parameters to action methods in POST requests, you've got several options. f:setPropertyActionListener was so popular in JSF 1.x, but if you're already at 2.x I would recommend you going with EL 2.2, which allows method parameter declaration. Being able to use it depends on the application server you're using, but even if not available you could import yourself. Then, you'll be able to do things like that:
<h:commandButton action="#{bean.saveCar(currentCar)}" value="Save Car" />
Use it wherever you can, it'll make things just easier.
For the view parameters, use <f:viewParam /> too. It's the standard JSF way of parsing the parameters from the GET request, so just let the framework do the retrieving work for you!
See also:
JSF 2 link, commandLink and outputLink example
Using EL 2.2 with Tomcat 6.0.24
What is the difference between redirect and navigation/forward and when to use what?

primefaces- graphic image not direct an url

I use primefaces 3.1, in menubar i want to add icon .When user click the icon,it will be direct to the home.jsf page.Below,when user click the icon,page goes to index but its url seems different.Thanks for any helps.
<p:menuitem >
<p:commandLink action="home.jsf" >
<p:graphicImage height="24"
width="24"
value="resources/images/home.ico"
style="border:none" />
<p:commandLink>
</p:menuitem>
Upon submitting of <h:form> by any command components like <h/p:commandButton>, or <h/p:commandLink> JSF performs a forward and not a redirect. That is why your URL stays the same. Just append ?faces-redirect=true to your action attribute and it'll work as expected. For the distinction visit BalusC's answers to What is the difference between redirect and navigation/forward and when to use what? and How to navigate in JSF? How to make URL reflect current page (and not previous one).
That said, it's a poor practice to perform navigation by using command components. Use <h:link> or <h/p:button> components instead. They trigger a get request to the navigation case outcome, thus, your URL will change. Command components are designed to trigger server actions and not performing plain navigation. For more information consult BalusC's answer to When should I use h:outputLink instead of h:commandLink?.

JSF CustomeScope reset for specified view

How can I control what customscope is created during request. Right now I have solution that when I click the commandLink:
<h:commandLink action="orders">
<f:actionListener type="com.mk.web.jsf.scope.ResetScopeListener" />
<span data-shortcut="F6" class="start_link">Orders</span>
</h:commandLink>
The custom scope is destroyed and a new one is created. But the problem is that the custom scope only resets if I enter the customers action using this commandLink from above.
When I enter to customers action by directly entering the url in browser the custom scope is not reset. How can I make that is customers action is loading even by commandLink or by url then always this custom scope should be reset. Can somebody give me some advice how to achieve this?
Thanks...
Typically you use a custom scope when you want your beans to live longer than the original request but shorter than the session. Based on your scenario though, it seems to me that your custom scope is behaving slightly like a request scope. Anyway, maybe I'm not understanding your scenario fully but one thing that comes to mind is that you can use system events in case a user decides to go to the next page when they type the address directly. So suppose the user tries to go to nextPage.xhtml, it could be defined like this
<f:event type="preRenderView" listener="#{bean.performPossibleCustomScopeCleanUp}" />
<h:head>
</head>
The (pseudo) method above will fire before the view root (aka nextPage.xhtml) is rendered. Inside the method you can check to see if your custom scope is still "alive" and you will handle it as needed. Keep in mind though that this event will be fired every time the page is requested. For instance, if you click the h:commandLink performPossibleCustomScopeCleanUp will still be invoked. There are ways around that
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
Just scroll down to the section Performing business action on GET parameters of the answer
An even better approach would be to implement a custom NavigationHandler through JSF's ConfigurableNavigationHandler API so you can keep track of the URL and perform actions as needed.
I didn't dig too dig so you might actually find a better code sample. Hope this helps.

How to move within only one part of the page

I have read many answers written mainly by BalusC but still no luck.
So I included via ajax rendering, a page in the part of the main page and it works perfect, whenever I click the button on the main bar the subpage xhtml is shown in the proper place. Now the problem is that i want to implement in that subpage a "selectOneMenu" so whenever a user clicks on one of the options he will be redirected to another xhtml which should appear on the same part of the page (instead of the previous page). I have already thought of many ideas to solve that(including conditional rendering), but I believe that there has to be much simpler and more correct way to solve it. Maybe JSF has some kind of container tag which could be used?
PS
By the way that is my first post so sorry if I didnt make something clear.
UPDATE
It appeared to me that maybe I should somehow use ajax onValueChange which would read the value (via the actionListener ?) so when the user clicks on subpage the main page would read the value and render part with the new content. Is that even possible?
You can use valueChange Listener to get the new value and in your bean using FacesContext you can redirect the page but make sure that you add ajax call to your selectonemenu if you dont want your page to refreshed.
<h:selectOneMenu value="#{some.value}"
valueChangeListener="#{some.valuechanged}">
<f:ajax event="change" listener="#{some.listen}" />
</h:selectOneMenu>

Resources