How to tackle double submit form? - java

How to handle a situation where user might accidentally click submit button more than one time? If it happens then two rows will be generated in table. How to avoid it.
I am working in JSP.
Also want to avoid back button and refresh page which cause to create a problem of double entry in database.

I'd suggest never to rely on anything client-side too hard. Using very accessible tools you can pretty much change any behavior that is client-side enforced. If your application crashes/has undefined behavior after something client-side fails, you should change your application.
One thing you could do is to make a class that takes all the fields resulting from this POST, override it's equals() method to honor all the fields, hold the request at the user level and compare all other incoming requests to the list of requests you already have for that user.
You can then remove the request objects as soon as they have been successfully processed.
If you, on the other hand, somehow get the same request again by the user (by looking through the list of 'open' requests whenever the user POSTs a request), you can just ignore it.

Several way:
You can use javascript to forbid two cliks in the submit button, but it does not work if the user use the "back" button of the navigator between the two clicks.
On the server side, you can send the form with an unique id kept in the user session (could also be used for CSRF counter-measure). Then when submitting the form you can compare then remove the id in the user session. Be carreful for concurrent access to the session (each request has its own thread).
Detect in the database, but it depends of the data and the constraints on it. One extension of the point 2 would be to keep the generated ID of the form in the database and removing it during the first access. This method has the advantage to user the transaction support in case of concurrent access.
If the form update an specific entry in the database (row id is sent with the form), the problem could be considered as solved by itself, as it update twice the same row with the same data.

First, on the client side, disable the button as soon as the user once clicks on it.
Second, on the server side, Some information in that form for will be a primary key in your database table. So when the same information is sent again to the server while inserting the data, you will get an exception since there cannot be duplicate values of primary key.

First solution . Disable sumbit button .. second check some unique key if possible ...

If you want to make 100% certain that the submit button cannot be clicked twice, you could disable it in the javascript within the onclick= method of the button.
For instance, in the javascript (jquery) below, if the button id was 'send'...
$('#send').click(function(e) {
this.disabled = true;
businessLogicCall();
});

Have a wait time for which you don't accept any more clicks on the button, for example disabling the submit button.

Disable the submit button until user changes the input information, thus showing he wants to submit another portion of information.

Related

How can I restrict the access of an action or URL in Java Spring?

I have a Java Spring app and I want that when a user is on a page of the app that another user can not access it and show him an informative message.
This is because I have a form that users must edit every day, so if two users enter the same form at the same time, they will see the initial data, but then when one saves and the other also, the data will be overwritten. of the first save.

MULTI-TABBING ISSUE For one of the Java Web Application - Mixing the data from two different records

Problem:
Whenever we save the data of two different records in two different tabs of the browser for the same session, data is getting mixed up for the respective saved records.
Scenario:
1) Tab1: Open the browser and login to the application and go the search screen. (In our case Guarantor search screen).
2) Tab2: Open another browser tab in the same browser, copy the URL of the previous step and paste it into the current tab, now search screen opened in both the tab.
3) Go back to Tab1 and search for one guarantor (for ex: Guarantor with some number like 34526) and open it once after getting the result in the search screen.
4) Then go to Tab2 and search for another Guarantor record and open the same.
5) Now Click on Edit button for editing the record opened in Tab2 and then go back to Tab1 without editing the data in Tab2.
6) Now Click on Edit button for editing the record opened in Tab1 and then make the modifications and do some action in this screen like 'SAVE' operation, at the same time Go to Tab2 and click on 'SAVE' operation on this screen also. Now Here we clicked the save button on Tab1 and in the mean time before Tab1 completes its save operation we did another action (i.e. SAVE) in Tab2 also.
7) Now data got mixed up for both the screens at this time (which is not a correct behavior). In this case data shouldn't be mixed up, it should be saved properly for the corresponding record.
Please note that in the above scenario opened screen will be same for both the tabs but with Different record. (For example: Opened the screen for 'Edit Guarantor' but with two different Guarantor records).
Preferred Solution By Client:
Application should allow to make the changes for the records opened in multiple tabs without breaking the application flow. The user logged into the application will be same in the case and application should allow multi-tabbing feature without mixing up of the data.
Possible Root causes for the issue are:
1) Browser version from IE 7 and above maintains single session throughout the browser, even if you open new window also it will be having the same session.
Since we are using IE8, it maintains single session even through different Tabs also. Which might be creating this problem.
We did some research on the above issue and also checked with some blogs but we are not able to trace the correct solution for our problem.
We checked few things to solve this issue like:
1) SessionStorage concept which is available from HTML5 and can support from IE8+ browsers but this solution won't support our requirement which we mentioned above. If anybody got the above results with the help of this please let us know.
2) We found another solution: URL re-writing - (appending the session details nd some unique details to distinguish the session and maintain some hidden fields to keep track of the session in each and every page) - But this is very complex and also we are not sure whether this solve the above said problem. Please let us know if any suggestions in this regard.
We also tried some examples with some JavaScript coding but didn't get required solution with them.
We are expecting some guidance or similar solution if somebody already implemented in their application.
Did you try setting the scope of your form bean to request? By default, struts's form bean is session scoped. So the bean that you are posting back to the server is shared between the tabs. If you set the scope to request, then you will have different form beans in different tabs. This will ensure that when the user hits save, data is not mixed up.
I have seen this issue with couple of struts applications which asks users to fill the data on multiple pages (users fills data on one page, clicks next ...reaches till last page and click on save and then the data is saved in the database). When user clicks on next to go to the next page, the current page (form) data is saved in the HttpSession (Struts automatically does that, if the bean scope is session). When the user opens the application in multiple tabs or browser windows (assuming user is using same browser (e.g. IE) for multiple windows) and acting on forms for different records, data gets saved/overwritten in the same session and gets corrupted. Your case is also similar.
As you rightly pointed out the jsessionID is little bit complex to implement because if you are rendering some links (links pointing to other part of the application from an xml file) on your web page, you need to embed the jsessionID in the URL otherwise server will assign a new jsessionID and will redirect the user to the login page (assuming your enterprise application asks the user to login first)( Dynamically generated link will have the jsessionID already embedded with them). Second problem with this approach is : if user right clicks on any link (assuming jsessionID is embedded in it) and select open in a new window/tab and then navigate to some other record to edit it, your data will get corrupted (Please note that when user selects open in new tab for a link, the URL for that link will already have the same jsessionID from the parent window/tab).
To solve the issue, you will have to make some design changes in your application. Below is the possible approach.
Rather than storing the data in HttpSession, you can store the data in a cache ( you can have your own logic to store data as key value pair, explained below ). I guess you will have to follow below steps:
a) Change the bean scope to request from the session.
b) Have a unique identifier for each window/tab. You can use windows.name property for the same. This property is supported by all the major browsers. You should send this tab/window name to the server each time you click on next/previous/save.
c) At server side to store the data, below approach can be followed (May not be the best one, feel free to tune it. :-) )
HashMap -> key will be the jessionID and value will be another HashMap.
- HashMap(value of the first Map) -> key will be tab/windows name sent from the browser. Value will be another HashMap.
- HashMap (value of the second map) -> Key will be form name. Value will be the actual form. (this map will have only one entry, if you have only one form).
d) Once you approach on the last page, get all the forms from the Map for the desired tab/window and save in the database.
For point (c) mentioned above, you can use the database to store the intermediate data. Both the approaches have pros and cons.
i) Storing/retrieving data in/from Map/Data Structure is faster compared to the database.
ii) Storing data in data structure consumes space on the heap. However as of now you store data in the session so that should not be an issue.
iii) Data gets lost in case of server crash, if stored in the DS. From the database data can be retrieved back.

Handling accidental multiple clicks in Java

When user clicks on the screen, a request is made to the database layer to store the data. However, when user accidentally double clicks or multiple clicks within a very short amount of time(like less than a second), multiple requests are being made to the database layer to store the same data. This is creating unwanted duplicates in the database.
The backend does have a check to see if a record already exists before inserting...But since multiple clicks on the screen generate requests at the same time, this unique check in the service is doing no good as it does not find the record.
How can I handle this situation with all the quick multiple clicks?
Usually a task like this would block anything else from being started, so it would be good to setEnabled(false) on the button being used to submit the entry. This will ensure any button clicks will be ignored. Just call someButton.setEnabled(true) when the query returns.

Are there techniques to prevent double submissions in stateless web applications?

I want to implement double submission prevention in an existing java web application (struts actually). Architecture wise we are talking about 2 to N possible application servers (tomcat) and one single database server (mysql). The individual servers do not know each other and are not able to exchange messages. In front of the application servers there is a single load balancer which has the ability to do sticky sessions.
So basically there are two kinds of double submission prevention client side and server side. If possible I want to go server-side because all client side techniques seem to fail if people disable cookies and/or javascript in their browsers.
This leaves me with the idea of doing some kind of mutex-like synchronisation via database locks. I think it may be possible to calculate a checksum of the user entered data and persisting it to a dedicated database table. On each submit the application would have to check for presence of an equal checksum which would indicate that the given submission is a duplicate. Of course the checksums in this table have to be cleared periodically. The problem is the whole process of checking whether there is a duplicate checksum already in the database and inserting the checksum if there is none is pretty much a critical section. Therefore the checksum table has to be locked beforehand and unlocked again after the section.
My deadlock and bottle neck alarm bells start to ring when I think about table locks. So my question is: Are there saner ways to prevent double submissions in stateless web applications?
Please note that the struts TokenInterceptor can not be applied here because it fails miserably when cookies are disabled (it relies on the HTTP session which simply isn't present without session cookies).
A simpler DB based solution would be something like this. This can be made generic across multiple forms as well.
Have a database table that can be used to store tokens.
When an new form is displayed - insert a new row into the token table
and add the token as a hidden field in the form.
When you get a form submit do a select for update on the row
corresponding to the token you received as a part of the form.
If the row still exists then this is the first submit. Process the
submit and delete the row.
If the row doesn't exist then the form has already been processed -
you can return an error.
The classic technique to prevent double submissions is to assign two IDs (both as "hidden" field in HTML Form tag) - one "session-ID" which stays the same from login to logout...
The second ID changes with every submission... server-side you only need to keep track of the "current valid ID" (session-specific)... if you get a "re-submission" (by click-happy-user or a "refresh-button" or a "back-button" or...) then that wouldn't match the current ID... this way you know: this submission should be discarded and a new ID is generated and sent back with the answer.
Some implementations use an ID that is inremented on every submission which eases a bit the check/kepp track part but that could be vulnerable to "guessing" (security concern)...
I like to generate cryptographically strong IDs for this kind of protection...
IF you have a load-balanced environment with sticky session then you only need to keep track of the ID on the server itself (in-memory)... but you can certainly store the ID in the DB... since you store it together with the session ID the lock would be on "row level" (not table level) which should be ok.
The way you described goes one step further by examining the content... BUT I see the content part more on the "application logic" level than on the "re-submission prevention level" since it depends on the app logic whether it wants to accepts the same data again...
What if you work with sticky sessions then you would be fine with some TokenManagement. There exist a DoubleClickFilter which you can add to your web.xml.
Since you have sticky sessions there is no need for a Cross-Tomcat-Solution.

Best Practice Updating DB Records

Say you retrieve 100 records, and display them on a page. The user only updates 2 of the records on the page. Now you want to update only the two records, and not the other 98.
Is it best to have one submit on the page, then somehow know which 2 are updated, then send only those two to the db for an update?
What does the "somehow" look like?
Or, would you have an update-submit button for each row, and have it only update the record its tied to?
Of course there are different ways you could do this. In general, you can save yourself some trouble and server-side processing by using Javascript to assemble your POST data for only the records that have changed. Two thoughts on how this might work:
1) Go the ajax route and do live-editing. So records are presented in a table and appear to be non-editable. When a user clicks a particular row, that row becomes editable by using Javascript to create the appropriate html form on the fly. Then have either a submit button or some other handler (say, moving focus to another table row) which will trigger the POST which updates the DB (asynchronously via your preferred ajax method). Happily the mainstream Javascript frameworks can help a lot in this area.
2) Checkboxes - whenever a row is edited, its checkbox becomes checked. When the submit button is clicked, use javascript to post the POST data by grabbing everything in row whose checkbox is checked. A user can un-check a box to cancel changes to that row before submitting.
Ajax it using jQuery or some other JavaScript library and put and update button on each row.
There are many answers to this question and to some extent they depend upon your development tools and the "feel" of the site.
If you were implementing Ajax calls to do the updates on a line by line basis then this would logically seem right to have a button per line and then update it with an Ajax call when a line was changed.
This is also just the scenario that disconnected data sets were designed to solve and ADO.net handles these very well.
So as ever, the answer is "It Depends!"
You can use JavaScript to mark each field as changed when a user changes an input field. Create a hidden fields that has the id of the row you are updating, and dirty flag. (like is_dirty_$id) In JavaScript, create an onChange handler that sets the hidden field as dirty. when any input is changed.
Alternatively, you can create hidden fields for each real field you display. the hidden field would contain the initial values. check each field on the server side to determine what has changed.
You probably want to store a last_modified date as a hidden field for each record. This way if another user updates the same record, you can display an error message saying "this record has been updated by another user" or similar.
One submit button. I could foresee case I might use more then one, but in the general case just one. (Note, this looks like a web page question to me, so I'm answering with that assumption.)
There are 3 ways that come to mind which you could handle the tracking changes:
JavaScript: Put a onChange() function on the controls that update a hidden field. If that hidden has a value, then update the associated record. Requires JS on the browser, and doesn't tell you which fields to update, just which records.
Lots of form fields: Put a hidden field out with each control and compare them all when they come back. This would be ugly, but it would allow you to know which fields to update (not just the record). It would also allow you to know if someone undid a change that started.
Sessions: You could place the original values in session variables, then do the comparison when the values come back. This would be a little more elegant then lots of hidden fields, and less open to people playing with the posted back data (since you should never trust anything that comes back, even in hidden fields). Requires cookies on the browser and sessions on the server technology.

Categories