I have a question about concurrent access in java.
The project context is as follows: JSF 2.1; Richfaces 4, hibernate 3.6, spring 3.2, java 7.
I have a table that displays hundreds of thousands of folders (each folder is a java object), each table line is a dynamic link to access the consultation or modification of the object(folder).
My question is: how can I prevent more than one user from viewing or editing a folder?
In other words, how do you detect access to a folder (object java) by more than one user at the same time?
I know that with the word Synchronized on methods makes it possible to prevent concurrent access, but I want to detect concurrent access to warn the other user or the other users that the folder (object java) is already open and we have to wait for it closed.
Thank you
Synchronization and all the other locking / blocking methods is only preventing concurrent access from within the code.
It does not prevent 2 users from editing the same "thing" at the same time. This is something you have to put into your code on your own.
There are two most common ways to achieve this:
Optimistic Locking:
You assume, that even if multiple users view the same item, there are not multiple changes at the same time. Hence, you only check during SAVING if there is a concurrent modification. To Achieve that:
The Object in Question needs a Timestamp, when it was last modified. (By anyone)
Once a user opens an item to view, you store that timestamp in the session context.
If the user clicks "save", you compare the session-context-timestamp with the timestamp of the actual object. If they are the same, changes can be saved. If the Object has been modified in between, you need to display an error, that it has been modified, and changes can't be saved without loading the new base-values prior.
Pessimistic Locking:
You assume, that whenever a user views an Object, that there will be a change. To Achieve that:
The Object in Question needs a Int-Flag, that it is currently beeing edited (By anyone - Flag = UserID)
Once a second user tries to load that object, you deny cause someone is editing currently.
Tricky part here is to clean up "locks", if the editing user just quits the page without "aborting" through application methods. To handle this, you need to define a Lock-Timestamp, define some timeout value (for example 30min) and do two more checks:
Editing user exceeded the timeout value upon save? he can't save anymore.
(As an extra you can allow later saving, if the object has not been locked by someone else in between, use the lock-user-id to figure out)
Object is locked, but lock is older than 30 minutes? Second User can open again, claiming the lock-user-id for himself.
Related
I have a situation like in a Java application like , "if an there is an entry in a table and simultaneously there is a delete request also how will we handle such a scenario".
Could anybody suggest me on how to deal with issues like these which could work on small as well as large applications?
I think the question is how the UI/UX should be handled when such scenario occurs. Besides the concurrency issue described in question, there can be other scenarios like user 1 opens edit person page, in the mean time, user2 deletes that record from another login. What should happen when user1 tries to save the record?
You should probably return an error message to the user stating the details of the error(record deleted, updated by someone else etc.).
Your question is very wide and such is the aswer.
I will narrow the problem a bit, by assuming you are using spring(boot). If so then It is very easy to answer.
Use the #Transactional annotation above the methods that contain the logic to either save or delete. And include required libraries ofc.
With the methods annontated in such a way, the spring(boot) application will guarantee that both operations will occur in the order that is required to maintain a consistent database.
If an error occurs, you can handle this in higher levels of your application or just show an error to the user.
I have designed a Web based project.
I am using Mysql database. I will perform all persistence logic in java using hibernate. All the client side actions will be done in javascript.
Here my problem is,
If two users are trying to update same record simultaneously at different places.
Initially User-1 updates by giving full information related to a single object and called save information method.
At the other end User-2 updates same record by giving partial information and called save information method.
If User-1 information is saved first User-2 information will overwrite first given information. Hence some information might loss which user-1 given but he doesn't know some thing is loosed.
Please give some suggestions to overcome this problem.
I recommend you use the Optimistic Lock. Basically this technique is to have a field in the table to tell Hibernate which your version and thus whether an object with smaller version try to overwrite the data in a larger version hibernate will throw an exception. This versioning field is usually a numeric field that hibernate increases with every update or date field. The flow is something like:
1 - The record is inserted into the base. At this point the "version" field is set to zero.
2 - The X user query the record with version 0.
3 - The Y user query the record with version 0.
4 - The Y user updates the registry information. At that moment the hibernate automatically increments the version of record for 1.
5 - The X user updates the information on the version 0 and try to save. At that moment the hibernate finds that the record is already in version 1 that is greater than the version that the user X is using, in that it throws an exception stating the problem and not allowing overwriting the most current information.
To implement this strategy simply create a numeric field in your table and then apply #Version:
#Version
#Column(name = "version")
private Integer version;
What you need to consider, is a locking strategy for your data. Using Hibernate, by default you have no locking (a.k.a. Ostrich locking or "last save wins"). Roughly, the other two options are optimistic locking and pessimistic locking.
Optimistic locking means that you do not prevent users editing data concurrently, but you will inform a user if his edit failed because the data was saved from elsewhere after it was loaded from the DB.
Pessimistic locking means that you prevent multiple users for editing the data concurrently. This is a bit more complicated form of locking and is usually neither practical nor required.
More info on implementing a locking strategy can be found from Hibernate documentation. Which strategy you should choose depends a lot on your application and whether many users are expected to frequently edit the same information.
Before user 2 updates the DB, you can check if the information in the DB (e.g. the row) is the same as it was when user 2 reached the update/edit page. e.g. you could do a SELECT on the row when the user reaches the page and again after the user has made the changes (i.e. before the row is updated) and compare these before you update the DB.
If the row is the same, there was no changes. If the row is different, someone else had edited it.
I have to solve this situation: in my Spring + JPA web application I have a jsp similar to an excel work sheet.
So I have a certain number of cells and each cell is saved in a DB table with additional information: I have a row for each cell.
id | value | column | row | ...
I use this structure because number of columns in my jsp table is dynamic.
At the moment, when I save cells I truncate the current set of rows in DB table and re-insert all the new rows. This is the fastest way I found to update a large set of rows.
But now I have a concurrency problem: the jsp page can be used by different users at the same time and this can cause overwriting problems on other users savings.
I need to implement some kind of lock in my web app. I found there are mainly two types of lock: optimistic vs pessimistic.
Can you suggest me a common approach to solve this situation? Where do I need to implement the lock, at data access level or at service level?
NOTE to be more clear: table values are shared among users, but can be updated by anyone among authorized users.
The solution would probably depend on the behavior requirements.
How about the following scenario: users A and B started to change some values, then user A pressed Save button and saved data, after that user B did the same. User B got an error message saying something like "the data has been updated, please reload the page". He reloads the page and lose all changes he did :( Only after that he is able to save his changes, but he has to do it once again.
Other possible scenario: users A and B accessing the page, but only the user who was the first will be able to save his work, other users will see message saying something like "someone else is editing the page, try again later".
For the first scenario you can implement the following: each line of the table (in database) has a last-update-timestamp which is updated to current time each time this row is changed.
Now, let's imagine user A get row with timestamp 1 when opened the page, user B was a little bit slower and got the same row with timestamp 2. But, he did his changes faster and pressed Save button first. Now, the row is saved in DB with timestamp let's say 5. User A is trying to save his changes, but the timestamp of his data is 1, which is different from 5 currently in DB. That means someone changed that data already and he should see error message I mentioned above.
Second scenario is a little bit harder to implement. I think the best way to do this is to open transaction to DB which
reads the row(s) we want;
put some flag like "locked" to true for all of them;
if some row is locked already, fails (or return available rows, depending on what you need). But, probably should fail;
returns rows to jsp page;
Now, if other user requested the same rows, transaction will fail and he will not be able to start changing data.
User A should put these locked flags back to false when he saves the data.
Important thing: these locks should have timeout to prevent situation when user opened the page and closed it without saving (or browser crash, or something else). You may also want to implement some kind of lock reackquire for the same user - when user opened the page for the first time, then closed it without saving data and opened once again - he should be able to edit the data. This can be done by identifying user somehow - login, cookie, and so on.
I would like to get some advice on designing a count based access control. For example I want to restrict the number of users that a customer can create in my system based on their account. So by default a customer can create 2 users but if the upgrade their account they get to create 5 users and so on.
There are a few more features that I need to restrict on a similar basis.
The application follows a generic model so every feature exposed has a backing table and we have a class which handles the CRUD operation on that table. Also the application runs on multiple nodes and has a distributed cache.
The approach that I am taking to implement this is as follows
- I have a new table which captures the functionality to control and the allowed limit (stored per customer).
- I intercept the create method for all tables and check if the table in question needs to have access control applied. If so I fetch the count of created entities and compare against the limit to decide if I should allow the creation or not.
- I am using the database to handle synchronization in case of concurrent requests. So after the create method is called I update the table using the following where clause
where ( count_column + 1 ) = #countInMemory#
. i.e. the update will succeed only if the value stored in the DB + 1 = value in memory. This will ensure that even if two threads attempt a create at the same time, only one of them will be able to successfully update. The thread that successfully updates wins and the other one is rolled back. This way I do not need to synchronize any code in the application.
I would like to know if there is any other / better way of doing this. My application runs on Oracle and MySQL DB.
Thanks for the help.
When you roll back, do you retry (after fetching the new user count) or do you fail? I recommend the former, assuming that the new fetched user count would permit another user.
I've dealt with a similar system recently, and a few things to consider: do you want CustomerA to be able to transfer their users to CustomerB? (This assumes that customers are not independent, for example in our system CustomerA might be an IT manager and CustomerB might be an accounting manager working for the same company, and when one of CustomerA's employees moves to accounting he wants this to be reflected by CustomerB's account.) What happens to a customer's users when the customer is deleted? (In our case another customer/manager would need to adopt them, or else they would be deleted.) How are you storing the customer's user limit - in a separate table (e.g. a customer has type "Level2," and the customer-type table says that "Level2" customers can create 5 users), or in the customer's row (which is more error prone, but would also allow a per-customer override on their max user count), or a combination (a customer has a type column that says they can have 5 users, and an override column that says they can have an additional 3 users)?
But that's beside the point. Your DB synchronization is fine.
I've been researching how to fix this issue for sometime but can't seem to find a proper solution.
Here's the issue:
I have a Java EE application where many users can login, they are presented with an item list, and they can select and edit any one of those.
All users see the same item list.
As mentioned, they can edit an item but I'd like to restrict the editing function to one user. That is, many users can edit different items simultaneously but only one user can edit a particular item.
When one user is editing an item, an message should appear to any other user trying to edit that item.
I have implemented this by setting a flag on the item, inUse, to true and then check for that. When the user is done editing the item, either by clicking save or cancel, the flag is set to false.
Problem with this approach is to account for cases when the user leaves his browser open or the browser is closed.
I tried setting a session timeout but can't seem to make that work because when the session times out, I don't have access to that item. I only have access to the httprequest session id.
Perhaps this is the wrong approach since it seems it's an issues that many applications would have and a less hackie solution should exist.
I looked into using threads and synchronized methods but don't know how that would work because once the user enters into the edit item screen, the method exits and releases the lock.
I found this solution Only one user allowed to edit content at a time but not sure if that's the way to go in Java.
Is there a more elegant/java solution? If so can you point me in the right direction please? How would you implement this?
Thanks!
The solution:
Although originally I thought optimistic locking was the way to go, I quickly realized that it wouldn't really work for my environment. I decided to go with a combination of pessimistic locking (http://www.agiledata.org/essays/concurrencyControl.html#PessimisticLocking) and timeouts.
When an item is accessed, I set an inUse field to true and the object's last accessed field to the current time.
Everytime when somebody tries to edit the object, I check the inUse field and the lastAccessed field + 5 mins. So basically, I give 5 mins to edit the user.
Do it like they do in a database, where a timestamp is used. The timestamp is kept with the record and when a person submits his edit, the edit does not go through unless the timestamp is the same (meaning 'no edits have occurred since I read this record'). Then when the edit does go through, a new timestamp is created.
First of all, in your persistence layer, you really should be doing optimistic locking, using a version/timestamp field.
At a UI level, to handle your use case I would do resource leasing:
Add two fields to your table:
LAST_LEASE_TIME: Time of the last lease
LAST_LEASE_USER: User that leased the record for the last time.
When a user tries to edit your record, first check that the record is not leased, or that the lease has expired (that is, the lease is not older that the specified lease time) or that the user is the one that was granted the lease.
From your web browser, periodically renew the lease, for example with an AJAX call.
When the user ends editing the record, explicitly expire the lease.
By doing leasing, you solve the "closed browser" problem: after the lease period expires without any lease renovation, the algorithm automatically "releases" the resource.
Sounds like you could use : Session Beans Quote:
In general, you should use a session bean if the following circumstances hold:
At any given time, only one client has access to the bean instance.
The state of the bean is not persistent, existing only for a short period of time (perhaps a few hours).
Martin Fowler describes 4 patterns for such a problem:
Online Optimistic Locking
Online Pessimistic Locking
Offline Optimistic Locking
Offline Pessimistic Locking
You should decide which one to use according to your problem.
JPA, JDO and Hibernate provide 1 and 2 out of the box.
Hibernate can handle 3 too, (I'm not sure about JPA and JDO).
None handle 4 out of the box and you shall implement it yourself.