Eric,
you must strictly define responsibility of components:
1. According to FBN spec, the client must implement all public methods of Data, including lock and unlock. This implies that it is client's responsibility to initialte locking and unlocking.
2. According to FBN spec, Data (or subclass) must allow clients unlock only those records that they locked. This means that tracking locks' owners is Data's responsibility.
3. In my design, Connection objects just relay clients requests to the database. Any other logic, including making sure you unlock only your records, are beyond of Connection's scope of responsibility.
Now, that said, I use ReadWriteLock design
pattern to implement locking. No explicit client ids needed. Data (or subclass) maintains a Map of Lock objects, every Lock knows who locked it.
I used the thread forked by RMI server as unique identifier of the client. While it worked perfectly, this is unreliable according to RMI spec (doh!), i think they took off points for that. You can use client's RMIConnection reference to uniquely identify clients for locking.
Look up ReadWriteLock pattern and look up this forum for more details, we have extensively discussed this.
Extension vs. modifying.
My approach always is modify only when absolutely necessary, extend otherwise. Modification was necessary tp replace deprecated API because they will become absolete in the future version of
java and the whole application will fail to compile and run.
Benefits of of extension are too great to ignore, i can't imagine why would anyone modify self-contained modules thereby ignoring ALL 3 (!!!) main concepts of OOP.
1. Extension supports Natural modeling. in my design Data is responsible for low level IO, SearchableDate for search algorithm(s), SafeSearchableData for locking. How easy is it to separately maintain each module? If you use source control each developer can keep working on each module independently of others.
2. Specialized behavior & polimorphism. You don;t need locking in local mode. So your ConnectionFactory can supply Data or SafeData based on selected mode. Since you polymorphically using these Connections your client has no idea whether or not locking is actually performed.
3. Better readability, simplicity, code sharing, blah blah.
The disadvantage is byte size slightly increases as does execution speed, but that all is marginal , could be dismissed.
Plenty of information about this on the net.
Hope this helps.