How to I set up a lock that will automatically time out if it does not get a keep alive signal?
I have a certain resouce I want to limit access to. Basically, I am using a session level lock. However, it is getting to be a pain writing JavaScript that covers every possible way a window can close.
Once the user leaves that page I would like to unlock the resouce.
My basic idea is to use some sort of server side timeout, to unlock the resouce. Basically, if I fail to unlock the resource, I want a timer to kick in and unlock the resouce.
For example, after 30 seconds with now update from the clientside, unlock the resouce.
My basic question, is what sort of side trick can I use to do this? It is my understanding, that I can't just create a thread in JSF, because it would be unmanaged.
I am sure other people do this ki开发者_运维百科nd of thing, what is the correct thing to use?
Thanks, Grae
As BalusC right fully asked, the big question is at what level of granularity would you like to do this locking? Per logged-in user, for all users, or perhaps you could get away with locking per request?
Or, and this will be a tougher one, is the idea that a single page request grabs the lock and then that specific page is intended to keep the lock between requests? E.g. as a kind of reservation. I'm browsing a hotel page, and when I merely look at a room I have made an implicit reservation in the system for that room so it can't happen that somebody else reserves the room for real while I'm looking at it?
In the latter case, maybe the following scheme would work:
- In application scope, define a global concurrent map.
- Keys of the map represent the resources you want to protect.
- Values of the map are a custom structure which hold a read write lock (e.g. ReentrantReadWriteLock), a token and a timestamp.
- In application scope, there also is a single global lock (e.g. ReentrantLock)
- Code in a request first grabs the global lock, and quickly checks if the entry in the map is there.
- If the entry is there it is taken, otherwise it's created. Creation time should be very short. The global lock is quickly released.
- If the entry was new, it's locked via its write lock and a new token and timestamp are created.
- If the entry was not new, it's locked via its read lock
- if the code has the same token, it can go ahead and access the protected resource, otherwise it checks the timestamp.
- If the timestamp has expired, it tries to grab the write lock.
- The write lock has a time-out. When the time-out occurs give up and communicate something to the client. Otherwise a new token and timestamp are created.
This just the general idea. In a Java EE application that I have build I have used something similar (though not exactly the same) and it worked quite well.
Alternatively you could use a quartz job anyway that periodically removed the stale entries. Yet another alternative for that is replacing the global concurrent map with e.g. a JBoss Cache or Infinispan instance. These allow you to define an eviction policy for their entries, which saves you from having to code this yourself. If you have never used those caches though, learning how to set them up and configuring them correctly can be more trouble than just building a simple quartz job yourself.
精彩评论