webpage expired when back button pressed on JSF(Richfaces) submit - java

My title maybe confusing so please read on. I'm using the following technologies if you may. Spring, Hibernate, JSF (RichFaces), MySQL, Internet Explorer.
I have a List of items which is displayed in a RichFaces datatable like so:
item a
item b
item c
item d
item e
On the same page I have the following buttons: search, edit, add, delete and new.
When an user enters a search string, e.g. "item c", and press search button, then it displays a list of matching items, e.g:
item c
When the user presses the new button, the request will be redirected to another page using:
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.getExternalContext().redirect(page + ".jsf" );
When the browser back button of IE is been pressed on that page, the page displays "web page expired". What is this and how can I avoid this?

web page expired
You will get this error when you're trying to obtain a non-cached POST request from the browser history. This behaviour is fully expected. To fix this "problem", you need to either turn the cache on or to replace POST by GET.
Enabling the browser cache is actually easy: just remove the Cache-Control: no-cache and related headers from the HTTP response of the POST request in question. The enduser will then only get a warning dialog that the POST data will be resent to the server, which in case of fully non-idempotent requests like placing an order or deleting an item is really not desirable. Replacing POST by GET is then a better solution. Getting searchresults (like as Google does) should really be done by GET.
Replacing POST by GET isn't easy in JSF prior to version 2.0. Best what you can do is to fire a redirect after the POST and pass the data of interest as request parameter which you retain from #{param} as managed property (more recommended) or store the data of interest in session scope (not recommended). A completely different alternative is to replace the JSF <h:form> by a simple HTML <form action="searchresults.jsf"> and do the search job in a #PostConstruct method in the backing bean associated with searchresults.jsf, after the submitted query has been gathered as managed property or from request parameter map.

Related

Post requests are not working properly with JMeter

i have a page that contains list of posts, each post has a comment link, which onclick of it it shows a text area (with javascript) and user fills this textarea and then presses enter to post the comment (with ajax), and here is the form data i see in the browser after posting the comment:
feedForm:feedForm
feedForm:j_idt221:0:j_idt222:j_idt286:commentText:hi
feedForm:j_idt221:1:j_idt222:j_idt286:commentText:
javax.faces.ViewState:-1278084094245361929:-1028657209799449340
javax.faces.source:feedForm:j_idt221:0:j_idt222:j_idt286:commentText
javax.faces.partial.event:keypress
javax.faces.partial.execute:feedForm:j_idt221:0:j_idt222:j_idt286:commentText feedForm:j_idt221:0:j_idt222:j_idt286:commentText
javax.faces.partial.render:feedForm:j_idt221:0:j_idt222:j_idt286:commentText feedForm:j_idt221:0:j_idt222:j_idt286:feedcomments
javax.faces.behavior.event:keypress
javax.faces.partial.ajax:true
what i did is i created a post HTTP request in Jmeter and added the above form data as parameters, and when running the test plan, i get no errors,but the comment is not added.
here's my JSF code for posting the comment:
<h:inputTextarea id="commentText" placeholder="#{msg['writeacomment.text']}" title="#{msg['writeacomment.text']}"
onkeypress="if(event.keyCode == 13 && !event.shiftKey){event.preventDefault();return true;}else{return false;}"
value="#{feedBean.commentText}" maxlength="2000" onkeyup="countChar(this, '#{msg['remaining.text']}')">
<f:ajax event="keypress" listener="#{feedBean.postComment(cc.attrs.value)}" render="commentText feedcomments" />
</h:inputTextarea>
please advise how to fix that.
The issue was that i was passing javax.faces.ViewState hardcoded in my post request, which was wrong, so i had to create User defined variable and CSS/JQuery Extractor for the view state in the previous request to be able to extract the view state and use it in the next request (off course in the same page).
references:
http://anahorny.blogspot.in/2011/03/jmeter-handling-dynamic-viewstate.html
http://jmeter.apache.org/usermanual/component_reference.html#CSS/JQuery_Extractor

Update the database from submit option

I have a jsp page having a 'submit' option for input.On clicking it i want to update the value of a table called tbIndividual.What can be the best approach to do it?
On jsp page i have somthing like this :
User Name : <%=rs.getString(2)%>
First Name : <%=rs.getString(4)%>
Last Name : <%=rs.getString(5)%>
Email Id : <%=rs.getString(6)%>
Contact : <%=rs.getString(7)%>
<input type="submit" value="ADD"></input>
And now i want to update the value of status of that particular individual from 'NO' to 'WAIT' state.On click of this submit button.
Is making new servlet for this task a good option or doing the code in jsp a better one ?
If i need to make a new servlet then what will be the code for it on jsp page .?Please help.
If you are trying to learn servlet with this project then you should create a separate servlet where you will perform your business logic (e.g addition of element in Db) and jsp should be kept away from business logic because role of jsp is to render the output not to produce the output.
If this is a project for production purposes, then you should ( IMO you must ) opt some web framework. As framework will reduce your effort, headache and increase productivity.
First of all, there are certain things you need to understand while developing web applications in Java. I have a few recommendations and inputs
Please don't use Scriptlets. Scriptlets are deprecated and they make your code clumsy and the maintainance will be hard. Use JSTL
You need to create a form in your html to have a set of variables to push them to the server on clicking submit button. The form will have an action attribute which contains the URL where the request should be sent
Create a Servlet and map with the action URL and write the doPost method which can receive the form parameters and do the business logic whatever changing the status from NO to WAIT or anything else
Please take a note that you need to have Session variables in order to have the store the data in between requests from the same client. eg browser.
Is making new servlet for this task a good option or doing the code in jsp a better one ?
Writing a new servlet is a good option, than doing the business logic in jsp page. jsp is meant for presentation, just view. They shouldn't be used to perform business logic
If i need to make a new servlet then what will be the code for it on jsp page .?
JSP should just have all the necessary html elements and attributes like form, action attribute etc.. to post the parameters in the request to the action URL. Please note the method attribute of form. You should use HTTP POST method for posting form parameters to the server
Note : Finally, Writing Servlets are also NOT recommended. Instead, you should opt for webframeworks like Spring MVC , Struts etc. Please go through the link to understand about web frameworks answered by #BaluC
Hope this clarifies.

Updating JSP content into session using struts2

Our application is developed with Struts2 and run on a JBoss server.
I have the requirement to develop a JSP page where the content of a grid will be displayed using <s:iterator> and <s:property> tag from a List (say ArrayList of person object) which is stored in session.
Now users can Add/Update/Delete the row(s) content generated by iterating session List.
For example if I have a list of size n of Peron object, and in JSP it's displayed as
name age contact
name1 24 1234456
name2 30 45654634
and so on...
Users can Add/Update/Delete any number of rows and then finally can save.
How to approach this requirement ?
This is dangerous... let's say that the power goes away, the session is not persisted everywhere.
So instead of updating the session n times and finally saving the data at once, you could simply save the data n times. But the requisite was thought to prevent too many access to the database (may be relevant with thousands of users), then you can use AJAX and Struts2-JSON-plugin like this:
Create an AJAX Action (in a <package> that extends="json-default" and return a <result type="json">), that implements SessionAware, and receives a row from the JSP;
in the execute() method, read your List from the Session Map, add the new row, then return SUCCESS;
in the JSP, create a binding to call your AJAX Action (a click of a button in the row, the onblur event, whatever you like).
Add a button to call another Action (AJAX or not, but it should implement SessionAware too) to save the data in the database. That action will simply read the List from the Session Map and save it in the database.
This way the user can change page, coming back and finding all the data previously entered, and you will avoid a lot of POSTs of the entire page (AJAX + JSON is a lot lighter).

Updating the url bar from the webapp to represent the current state

I would like to basically do what Jason asked for here
In one sentence, I would like the url bar to represent the state of the AJAX application so that I can allow to bookmark it as well as allow the user to return to the previous state by using the back/forward buttons in the browser.
The difference for me (From what Jason asked) is that I am using JSF 2.0.
I've read that JSF 2.0 added the ability to use get, but I am not sure what the correct way to use this.
Thanks for the help.
Further Clarification
If I understand correctly, to be able to bookmark specific states in the AJAX webapp I will have to use the location.hash. Am I correct? I'm trying to achieve a gmail-like behaviour in the sense that, while the app is complete AJAXified and no redirects occur, I can still use Back/Forward and bookmark (And that's why I would like the URL bar to be updated from the AJAX app itself and not through redirection)
Update
Just found this similar question
The difference for me (From what Jason asked) is that I am using JSF 2.0. I've read that JSF 2.0 added the ability to use get, but I am not sure what the correct way to use this.
Please note that this is not the same as maintaining the Ajax state. It usually happens by fragment identifiers (the part starting with # in URL, also known as hashbang). JSF doesn't offer builtin components/functionality for this. As far I have also not seen a component library which does that. You may however find this answer useful to get started with a homegrown hash fragment processor in JSF.
As to using GET requests, just use <h:link>, <h:outputLink> or even <a> to create GET links. You can supply request parameters in the h: components by <f:param>. E.g.
<h:link value="Edit product" outcome="product/edit">
<f:param name="id" value="#{product.id}" />
</h:link>
In the product/edit.xhtml page you can define parameters to set and actions to execute upon a GET request
<f:metadata>
<f:viewParam name="id" value="#{productEditor.id}" />
<f:event type="preRenderView" listener="#{productEditor.init}" />
</f:metadata>
In the request or view scoped bean associated with product/edit.xhtml page -in this example #{productEditor}-, you just define the properties and the listener method. The listener method will be executed after all properties are been gathered, converted, validated and updated in the model.
private Long id;
private Product product;
public void init() {
product = productService.find(id);
}
Normally you'd use AJAX to prevent complete page refreshes. AFAIK all current browsers would issue a page refresh if you change the base uri. Thus you would have to use the hash part as suggested in the question you provided.
We had a similar problem and did something like this:
We settled for the fact that users cannot bookmark the url.
For URLs that should be unique/bookmarkable we used different links that issue a redirect. Those URLs are provided in a sitemap.
For browser back, we added an intermediate page after login. This page does navigation and a redirect to the application. The navigation is stored in the session and when the server gets a navigation request (which can be a history back) the corresponding state is restored. A browser back opens that intermediate page which issues a redirect along with a navigation request on the server side.

Handling the browser 'Back' button in jsp

I have a jsp search page (Search.jsp) and a result page (Result.jsp), both of them can choose search criteria. and then passed the parameters to a java controller file (Controller.java) to build a query string and performs query searching. The query string and searched results will be passed to Result.jsp for displaying.
Currently I use servletContext to remember the processed query string, and if users use Result.jsp to select search criteria, Controller.java will append such criteria to the existing query string. If I do a few searches using Result.jsp. For example, query string would display ((Query1) AND Query2) AND Query3 on the Result.jsp page. Then using the browser's back button to go back to the previous display page. For the same example, query string displays (Query1) AND Query2. Then if I do search again. The query string (((Query1) AND Query2) AND Query3) AND Query4 would be used. I know this is expected with my current implementation since Result.jsp does not do any modification with the processed query string.
However, I would like when user uses the browser Back button, for example, query string displays on the page as (Query1) AND Query2, and perform search, the query string should be ((Query1) AND Query2) AND Query4 in which the query string is build based on the current displayed query string on the Result.jsp page plus the current selection. How can I do that? It sounds quite simple but I have tried several ways of using the in Result.jsp to update the query string, but still couldn't get it right. Therefore I am wondering maybe my approach of using <c:set> is wrong. I would like to hear your suggestion. Thanks in advance.
Currently I use servletContext to remember the processed query string
Do you realize that the ServletContext is shared among all users/sessions who are visiting your webapplication? Once visitor X modifies it, the changes are reflected for all other visitors. Don't you rather want to store it in the HttpSession to keep the data visitor-specific?
See also:
Servlet lifecycle and multithreading
I want to use back button for some reason
I really have a hard time in understanding your functional requirement (the some reason part). But at least, since you'd like to have the back button to work properly, you'd like to use idempotent requests here. So, where applicable, replace POST by GET.
Whenever you'd like to refire a real HTTP request on the server instead of loading the page from browser's cache, you'd like to instruct the browser to not cache the pages by adding the following headers to the response:
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
You can do that in your controller or some Filter covering the url-pattern of interest.
See also:
Make sure that a webpage is not cached across all browsers
Webbrowser caching tutorial

Categories

Resources