jsf - intercept when user departs page - jsf

I have the following 3 simple pages in a JSF app.
index.html
start.html
confirmSuccess.thml
start.html is a simple form, with a "GO!" button and a html link back to index.html. When the user clicks GO! it kicks of a transaction in the backing bean. If this fails, I want start.html form redisplayed, but with an error explaining failure. So, I have an error flag set in my backing bean, and the error display is managed using rendered="" attribute.
Simple, right?
So, how do I handle the case where the user then clicks the html link to index.html, and from index.html clicks the link back to start.html, or simply clicks back. That is, how do I clear intercept that user has departed the start page, and clear the error flag so I know second time around that I don't need to display the error.
Is this possible without getting deep into the bowels of JSF lifecycle management?
Note The 3 pages listed is a gross oversimplification of my webapp, in reality, there multiple pages a user can go to from start.html, so I don't want to have a solution where I need to track the page someone arrives at to clear flags for start.

Sounds like you're transferring request scoped data around in a session scoped bean. Make the bean which holds request scoped data request scoped and instruct the browser to not cache the dynamic pages so that it is forced to re-request the page from the webserver instead of from its history.
That said, I'd rather use a combination of FacesContext#addMessage() and <h:messages/> to display errors. You can use an clientId of null to denote global message. They are in turn already request based so that you don't need to hassle with a flag to render/unrender an error display.
E.g.
public void submit() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Error!"));
}
with
<h:messages globalOnly="true" />

Related

The page change but not the URL on clicking <p:commandButton> [duplicate]

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?
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:
What is the difference between redirect and navigation/forward and when to use what?
JSF implicit vs. explicit navigation
What URL to use to link / navigate to other JSF pages
Bookmarkability via View Parameters feature
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
When should I use h:outputLink instead of h:commandLink?
Creating master-detail pages for entities, how to link them and which bean scope to choose
Retaining GET request query string parameters on JSF form submit
Pass an object between #ViewScoped beans without using GET params

getViewId(), getServletPath() and getRequestURI() all returns previous URL, how to get current URL? [duplicate]

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?
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:
What is the difference between redirect and navigation/forward and when to use what?
JSF implicit vs. explicit navigation
What URL to use to link / navigate to other JSF pages
Bookmarkability via View Parameters feature
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
When should I use h:outputLink instead of h:commandLink?
Creating master-detail pages for entities, how to link them and which bean scope to choose
Retaining GET request query string parameters on JSF form submit
Pass an object between #ViewScoped beans without using GET params

Start webapp (EJB3+JSF2) with method from bean instead of page

I'm pretty new to EJB + JSF and I'd like that my webapp's entry point would be a method of a bean instead of a view.
I mean, when someone types www.mypage.com I'd like it to go to a method of a bean and then be redirected to a view rather than go to any xhtml... how can I do this?
EDIT:
I need to load some data from the database to show it in the view that the user sees when he enters the app. It's not authentication, it's just that I need some data to be loaded before the user sees the website.
Annotating the method that loads the info with #PostConstruct gets the work done :D Thanks to Luiggi Mendoza http://stackoverflow.com/users/1065197/luiggi-mendoza

How to navigate in JSF? How to make URL reflect current page (and not previous one)

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?
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:
What is the difference between redirect and navigation/forward and when to use what?
JSF implicit vs. explicit navigation
What URL to use to link / navigate to other JSF pages
Bookmarkability via View Parameters feature
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
When should I use h:outputLink instead of h:commandLink?
Creating master-detail pages for entities, how to link them and which bean scope to choose
Retaining GET request query string parameters on JSF form submit
Pass an object between #ViewScoped beans without using GET params

How to avoid BusyConversationException in jsf

I'm getting BusyConversationException while navigating through pages in my jsf project. This mostly happens if the user tries to navigate to another page during an ajax call. This also happens when the user clicks on a link right after clicking on another link without waiting for loading of the page.
For example if the user clicks on more than one link which are generated through a code similar to below one we definitely get this exception. Another example is, lets say the user enter a query on a text field, and our application make an ajax call for searching this query. During that query if the user click on some button to navigate to another page BusyConversationException occurs too.
<h:commandLink value="#{theProfile.profileName}"
title="#{theProfile.profileName}"
action="#{profileBean.aProfileSelected}">
<f:setPropertyActionListener target="#{currentProfileWebBean.theProfile}" value="#{theProfile}"/>
</h:commandLink>
I can catch this type of exception in an ExceptionHandler class which extends ExceptionHandlerWrapper class but I can't save my current state and the best I can do for this case is to redirect to main page when this exception occurs.
Is there any solution for avoiding this? Thanks in advance for answers and comments.
As mentioned in the other answers, this happens if an ajax request is still being processed or if an ajax event is triggered prior to the actual click on the submitting commandLink or commandButton (for instance by a change event on an input field).
Therfore it is not possible to avoid BusyConversationExceptions with onclick="preventEventPropagation(event)";, since the AJAX events are not triggered via propagation.
The issue can easily be avoided by listening for running ajax requests and blocking submits until the pending ajax events have been completed.
The issue and solution are explained in more detail in this blog post JSF2 AJAX/Submit conversation issue.
i found this,
Indicates that the container has rejected a request because a concurrent request is associated with the same conversation context.
The container ensures that a long-running conversation may be associated with at most one request at a time, by blocking or rejecting concurrent requests. If the container rejects a request, it must associate the request with a new transient conversation and throw an exception of type BusyConversationException from the restore view phase of the JSF lifecycle.
refer here
I've been seeing this occasionally too. I'm starting to think it's a good idea to put some effort into serializing access to conversations:
Avoid propagating the conversation ID (cid) when you don't need that conversation instance for the target view. Specifically, unrelated navigation links/buttons should suppress the cid parameter (haven't thought about exactly how to do that)
When starting a request that uses an active conversation, disable other UI elements that propagate the conversation and could therefore cause concurrent access. The PrimeFaces or (even better) PrimeFaces Extensions blockUI components work well as a translucent overlay, along with a PrimeFaces p:ajaxStatus to show the busy status.
Begin conversations as late as possible. This will minimize the cases where a long-running conversation would be propagated.
I don't think that any of this is a complete solution, though. As soon as the cid ends up in the location bar (which happens when you do a non-ajax post back of a form when a conversation is active), you potentially lose control over the timing of access to that conversation due to multiple tabs/windows, bookmarks, etc.
I also faced the same problem, when I used to click the .
I have read in one of the book, busyConevrsation happens with that event two actions are happening, so they said use : onclick="preventEventPropagation(event)"; in commandLink to prevent the event propagation for that click. So I have used the same and it's working for me.
So now am not getting the BusyConversationException :)

Resources