Which of these operations require more time and resources? Getting cookie value or getting data from DB?
They both serve a different purpose. Cookies are used to store preferences and are disposable in a sense that if they aren't available (like the client deleted them) the preferences switch to defaults.
Database on the other hand would store data that should persist through-out the application's life. For example, user login data. You can't save that as cookies for security reasons as well as that you may lose them any time.
Cookies can only save text whereas you can practically save anything in a database as binary objects.
Any preferences saved with Cookies would only take effect if the user uses the same browser that the cookies were stored on. So, databases are also more suited for any preferences that should be mobile.
Related
We are developing one social networking site, which has to maintain lot of data for notification (unreal notification, which is nothing but the notification for the activities done when the user is not logged in).
Once the user logs in we will be fetching lot of data in the form of JSON. There will be around around JSON objects, each JSON will inturn consist of min 1000 characters, this data must be available in all pages the user navigates, so we are keeping all the data in the session.
How feasible it is to keep such data in session?
Is there any limit for the amount data we store in session?
Keeping huge data may sometime lead to hinder the performance of the application.
What is the most optimized way of handling such data if this is not the proper one?
Is there any limit for the amount data we store in session?
There is no limit how much data you put in your session, but there is only limit of space in your computer.
But,
To put lot of data in session lead performance degradation of system,
you can do one thing use temporary database table which will keep only values that use required when he navigate through application and the populate each time when user visit that particular page. I think round-trip no more costly then session in your scenario.
I am java developer and my application is in iOS and android.I have created web service for that and it is in restlet Framework as JDBC as DB connectivity.
My problem is i have three types of data it is called intersection like current + Past + Future.and this intersection contain list of user as a data.There is single web service for giving all users to device as his/her intersection.I have implement pagination but server has to process all of his/her intersections and out of this giving (start-End) data to device.I did this because there are chances that past user may also come in current.This the total logic.
But as intersection grows in his/her profile server has to process all user.so it become slow and this is obvious.also device call this web service in every 5 minutes.
please provide better suggestion to handle this scenario.
Thanks in advance.
Ketul Rathod
It's a little hard to follow your logic, but it sounds like you can probably benefit from caching your results on the server.
If it makes sense, after every time you process the users data on the server, save the results (to a file, to a database table, whatever). Then, in 5min, if there are no changes, simply return the same. If there were changes, retrieve from cache (optionally invalidating the cache in the process), append those changes to what is cached, re-save the results in the cache, and return the results.
If this is applicable to your workflow, your server-side processing time will be significantly less.
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.
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.
I am working currently on a web project where users can create image galleries and upload pictures. Optionally they can mark pictures as private so that nobody else can look at them.
Now i am not sure how to properly implement the protection mechanism. Of course i have some ideas but none of them seems to be optimal.
Here is one of my ideas:
Create a table for user images:
image_key (PK) | user_id | public_image (boolean)
the picture will be saved on the harddisk using the iamge_key and can be accessed via http by an url looking like this:
http://www.myCompany.com/images/image_key
a servlet will be mapped to the url path images, the key will be extracted, a stream to the file on the harddisk will be openend and the picutre will be streamed.
additionally there will be a reverse proxy in front of the servlet container to provide some caching.
The issue with this solution is that my serlvet would have to go to the database and check if the image with the given key is public or not.
My question:
Can this be done without hitting the database? (some fancy ideas)
Can someone provide a better solution to store and keep track of the pictures?
How would a solution look like where besides public and private pictures also some pictures are shared to firends only?
Please note that this question is not about storing pictures in a database or somewhere else but concerns access rights management of binary resources in a web application environment.
If the DB table is properly indexed and you're using a connection pool, then hitting the DB is cheap. I would just keep it as is. You can at highest have a copy of the table in a Map in the application scope. But this may eat too much server memory. If you're using an ORM framework like JPA/Hibernate, you could also just turn the second level cache on to delegate the caching to the ORM. It will generally do its job very well.
As to the client side caching, you'd like to have a short expire time (1 hour?) and provide a doHead() in the servlet which in turn does basically just the same as doGet() but then without writing any bit to the response body. You would also like to check for If-None-Match and If-Last-Modified headers in the servlet if the client supplied them. You can find here a basic example of a servlet which does that.
My question: Can this be done without
hitting the database? (some fancy
ideas)
Yup, you can do it without hitting the database. We've got something similar and just wanted to put something quick in place.
The user is marking the resource private or public when he's uploading it.
We do something very simple:
public resources have a "tinyurl like" URL, say: abcd.org/aZ3tD (part of the point of the very short tinyurl-link thing is so that people who want to cut/paste/twitter it don't have to use an additional layer of bit.ly or tinyurl)
private resources aren't meant to be shared nor archived, so users don't care about a URL looking like: abcd.org/private/da499c3314e2fdce6a10a8b985489671971c187d
The first part of that URL is the user's ID.
So only the user da499c3314e2 (which must be logged in) can access resource fdce6a10a8b985489671971c187d
You asked for some way to do this without hitting the DB, this should work...
To avoid having to go to the database so often, how about the following URL patterns:
1. http://www.mycompany.com/images/<user_id>/public/<image_key>
2. http://www.mycompany.com/images/<user_id>/private/<image_key>
3. http://www.mycompany.com/images/<user_id>/shared/<image_key>
For 1, obviously no DB lookup is required - the image can be served to anybody immediately. For 2, your servlet would have to check that the ID of the active user matches the user_id in the request - again, hopefully no DB lookup required, just a check of a session variable.
The only case in which a DB call would be needed is 3, to check the relationship between the requesting user and the user who owns the image.
Of course, you'll need to be very careful about caching to ensure that your cache doesn't serve up private or shared images to unauthorised users...
Another alternative can be to store such information in image metadata.
Image metadata API: http://download-llnw.oracle.com/javase/1.4.2/docs/api/javax/imageio/metadata/package-summary.html
You can find related example:
http://download-llnw.oracle.com/javase/1.5.0/docs/guide/imageio/spec/apps.fm5.html
Write dpi metadata to a jpeg image in Java