My supplied iface does not use locking cookie. It provides lock & unlock methods. I have already implemented all the functionality, but I have couple of questions:
1. Should calling RMI client make locking?
2. Should find, create,delete,read make locking? (inside method)
3. Should I expose DMainRemote (same than DBMain + RemoteExceptions + implements Remote, through adapter) to RMI?
a) if 1. is true, the locking will be made by client using the server. This leads to problem that it's not really clients job to lock records.
4.Should I make my business layer to Server side ??
SCJP 5.0, SCJD URLyBird 1.3.3, OCMJEA 5 (SCEA) Factory Homes
1. If I understood what you meant (if the client should be using the locking directly), it depends on your approach of using either a fat client or a thin client (and this answers question #4 too). You can choose to have your business/services layer on the server, and have your client use it. I chose to have a fat client, that is, the client calls lock/update/unlock.
2. Please take a look here. I think it might be helpful!
3. This was my approach.
4. It depends on your choice of either fat client or thin client.
If you still have doubts, please let us know so we can try to help you!
Did you use caching? I hav implemented caching, but i'm having doubts.. (When to write to actual file??? 1. To file 2. to Cache ??, this lead to double locking mechanism since fileaccess should be thread safe also)
here's what I did: all methods of my Data class are synchronized, so it's guaranteed that the access to the .db file is safe.
Please take a look here (this one you'll remember) and here. This might be helpful!
One of the most spirited discussions we have had in the SCJD forum revolves around whether you need a thick client that performs the locking, or whether a thin client calling business methods is desirable. You can read about it on "Should lock methods be callable by the client".
As a variant on Bob's code, you could have your networked method [e.g. update(record, ownerId, data)] set the thread-id on the server side. As long as all your business methods do this, then the thread ID should always match your ownerId. It wont matter if a different thread is used for each of the steps [lock, update, unlock] as the thread ID will have been set correctly as each remote method is called.
Alternatively, you can have a remote factory that returns instances of a remote class that provides your functionality. That returned instance will then be unique to the client using it, giving you multiple ways of identifying the client [hidden client ID, "this",...] without requiring different methods in the client depending on mode (so client always calls update(id,data) rather than having different update() methods for local versus remote).
Ok, read everything and i'm keeping my design (already done, except GUIController):
iface DBRemoteMain (same than DBMain + RemoteExceptions)
Locking/unlocking is made in client side (except create)
.db-file read in the beginning and written in the end (with hooks)
RoomService holds Business methods
Remote way needs some refactoring though, it's beginning to be too complex. I also have to rename some classes according to responsibility.
Used hours: 29,5h (documenting every monent)
Comment, suggestions, criticism?
Joined: Jan 16, 2004
Ok, just wanted you to know, that i remade the whole server logic. I removed caching and my own locking mechanism. They worked fine, but where way toooo complicated for Junior Developer. I'm locking with ReentrantLocks and file is now accessed directly.
ReentrantLock has everything ready: isHeldByCurrentThread(), lock(), unlock()....
Although I learned a great deal when making everythinhgmy self - it's time to let go now
Time spent 48h:
100 % Sercvice
50% Server (now when i'm remaking it, including tests)
I'm going to do at least two refactoring rounds.
Joined: Jan 16, 2004
I made all necessary changes and now I'm much happier with my solution. ReentrantLock/Condition is working fine. Now i'm opening new RandomAccessFile to every new operation. This is not what i would do in real life situation, but this is nothing to that kind of situation. Better solution would be to use ConnectionPooling for RandomAccessFile objects. I'm going to publish my Data-class testing routine here in near feature.
My Swing GUI is using Visitor pattern (ActionListener) to get all interactions. ActonListener only get's source object, casts it to Command pattern inteface and calls execute-method. Every action-making-component is sub-classed from it's original (JButton, JFileChooser) and they're implementing Command interface with exceute-method respectively. These components are protected classes in my own Panel-classes. This way I can have multiple reusable panels (e.x. Save, Cancel / Info splash) and plug then to any existing JFrame/new view.
Ok, finally all coming to near end. I also decided to change lock implementation to ReentrantReadWriteLock. Javadoc is done and i checked everything with Doc Check. Choices.txt also done. I'm starting to make user documentation which should be no brainer.
Last I will run some concurrency tests and the submission + exam.
ps. Without record cache: Stand alone mode, GUI startup + 15 000 rows = under 3 seconds (no special tweeking)