Building on an earlier thread here, I've some ideas about identifying individual running clients even if there are several on a single machine.
My Data class uses a crude form of dependency injection to receive a lockmanager from the class that instantiates it. That lockmanager itself if it's a networked lockmanager receives through a similar system a callback method to the Remote to supply it with a client identification String.
The Remote is a wrapper around the Data class to provide network services (so a decorator), and could be extended with a system to receive a unique identifier from the client calling it.
The client itself knows only it has a Data, though in the case of a networked client what it actually has is a proxy around a Remote stub.
My plan is to expand the remote to have calls requiring it (lock, unlock, update, delete, my create doesn't lock anything) send a sort of UUID over the line. That would be created on the client when initialising the proxy, either by a call to the Remote (which would then need a method to hand out such IDs) or by generating it itself (like Windows generates GUIDs but simpler).
The Remote could store this (it would have to as there's only one of it and could be running several requests at once) using ThreadLocal and then in the callback method retrieve it from the ThreadLocal and send it to the lockmanager. Problem is I've never used ThreadLocal before, and I'm wondering it is appropriate for this purpose.
Sounds intriguing. I am willing to bet that the reason this sounds so complicated is because you are trying to avoid crossing our boundaries regarding amount of lock() code published. I suspect that if you were to post real code it might not be as complicated as it sounds.
If I am understanding you correctly, you will have some method exposed to the client that might look something like:lock(recordNumber, clientIdentifier)When you receive this on the server side, you are calling a method in your lock manager to state who the client is, then delegating the remainder of the method to Data's standard lock method. Sound right?
If so, have you considered just setting the thread identifier with your client identifier when your server's lock() method is called, and then delegate to the Data class' lock() method? Would that simplify your concept?
Something like that. The RemoteData will have that method insted of lock(long), and the DataProxy will expose lock(long) to the client and determine the actual client ID, thus hiding from the rest of the client application that it's running in networked mode.
The lockmanager is an abstract class which relegates just the actual storage to a networked and non-networked subclass (the non-networked version obviously has no need to track clients).
Using the thread ID to store the client ID sounds like a good idea. Would indeed remove the need for a bit of code and another class.
I can't help feeling though that I'm going overboard here on functionality and flexibility (having turned even the locking system into a pluggable architecture).
So you try to avoid the classic "Data instance" client identify mechanism, and for this you send from each client an id. On the server side you pack this information "in to the thread" (in to each thread) using the ThreadLocal. The Lock Manager uses them to identify the client.
But why you decide to to this ? Because of :
My Data class uses a crude form of dependency injection to receive a Lock Manage r from the class that instantiates it.
you mean because in your actual design the Data and the Lock Manager are to strong related ?
If I am right(I hope), this is quite a challenging issue, but I am afraid that you may "jump over the shark" with this.
Regards M. [ July 17, 2006: Message edited by: Mihai Radulescu ]
The Data and LockManager were too strongly linked. Now the only link is an interface, an instance of a class implemented by something is injected through a setter or constructor into the Data instance.
The Data class knows nothing about clients, it knows only about incoming requests for data or other services (which of course have no client information). And there's the crux, because the Data class has no client information it can't pass that information to the LockManager thus I have to find some other way to make the LockManager aware of the individual client instances making each call.
I think that I am lost, The Data need a Lock manager to fulfill its lock/release tasks. And I still can not understand how the Lock manager (and the Data) get the user information and how they use it. Jeroen, Andrew, please help me to understand.
The Data gets a LockManager from the outside world, it doesn't know what kind of LockManager it's getting. All it knows is that it has something implementing the LockManager interface which has methods lock(), unlock(), isLocked(), etc.. The LockManager similarly gets the client identification passed in from the outside (if it needs it, only some LockManager implementations do). It gets an instance of a class containing a method it can call to give it that information. That class happens to be an inner class of the RMI enabled decorator I built around my Data class.
Sorry for the delay, I was pretty catch. As far as I understand : you have two(or more) lock manager types (a network and a local). The lock manager gets the information about the client - only in the remote (network) mode - from some helper class.
That means lock method are like look(record) ? Why you think that we need more than one kind of look manager ?(you mentioned network and local) What make you choose this design ?
On my URLy I have a lock manager with lock method like : look(user, record). If a user lock a record only this user can release it, otherwise an exception raises (OK I must admit this is a weak point). The Data class gets a LockManager, each client has a Data instance (all the Data instances use the same LockManager instance but the LockManager is not a singleton) - so I can guarantee the unique id for the clients.
Maybe not strictly needed, but it adds flexibility. I could create for example a lockmanager to call an outside service rather than have it internal to the application. More than is called for, but the option is now open.
That's part of me designing the application for easy expansion, which is a requirement
I could create for example a lockmanager to call an outside service rather than have it internal to the application.
Aaaaaa, now I get it. So by any lock instead to use a lock manager you ask your "lock service" to lock (the thread) for you, the service can be easy to extend later. If you have a Data instance for each client you can call this service with userId and record. Something like :
That's a future possibility indeed. I've provided hooks for user security in the application in several places which at the moment are just stubs. That too could be implemented in a possible future expansion by providing implementations for those stubs and plugging them in.
I do some of my very best work in water. Like this tiny ad:
Free, earth friendly heat - from the CodeRanch trailboss