this is a description of my architecture. I am doing the URLyBird.
I defined a class called Record which is a wrapper around the String record in the database which defines a room and contains other information (rowNumber, deleted flag)
I have a DBMain interface and a Data class that implements DBMain. The Data class has a reference to two singletons, LockManager and RecordManager.
RecordManager is used to access and persists Records. All his methods are synchronized since I want to make sure access to the file happens sequentially. I do use a cache when reading a record, and when writing a record I update the cache while writing the record back to the file. I have also a list of deleted records to reuse when create
LockManager maintains a weakhashmap where a logical lock on a record by a DBMain instance is stored. Access to this weakhashmap is synchronized. I assuming every client is using a different DBMain instance (I don't have cookies)
I have two remote objects, DBMainAdapterPool and DBMainAdapter. The DBMainAdapterPool maintains a pool of DBMainAdapter in a HashMap. The DBMainAdapter wraps a DBMain instance and exposes two business methods for searching and booking, which use the methods exposed by the DBMain
To get a reference to a DBMainAdapter the client has to lookup the DBMainAdapterPool, and call its method lookupAdapter, which returns the JNDI name for an available DBMainAdapter. The client then looks up this name for a DBMainAdapter instance. When done with it, the client calls the method releaseAdapter(String adapterName) so that the adapter can be returned to the pool and another client can use it. I synchronize calls to lookupAdapter and releaseAdapter, so that two clients don't get the same DBMainAdapter instance
The gui maintains a reference to a DBMainAdapter during his lifetime and releases it on quitting. The DBMainAdapter asks the pool to release him when unreferenced().