I searched through the archives but did not find a satisfactory solution to this problem in Contractors. I have created the DBAccess interface according to the specifications. The Data class implements this interface. (Note: I am using Max's indispensable book as my primary resource for this assignment.) A DataAdapter class maintains a reference to a Data object, and shields clients from the complexity of locking and unlocking records. (Is this an adapter or a proxy?) The DataAdapter also implements the DBAccess interface. Now, I have chosen to use RMI for the network layer. A DataRemote interface extends the DBAccess and Remote interfaces. A DataImpl class implements this interface and extends UnicastRemoteObject, and therefore is the class representing the remote object. The client will request a connection via a ConnectionFactory, which will return a DBAccess. Everything seems ok so far. However, rmic fails because the implementation of the methods in the DataImpl class do not throw RemoteException. Nor can they, because the DBAccess interface does not throw them. How do we get around this? Several threads suggest having DuplicateKeyException and RecordNotFoundException extend RemoteException. This seems bad, because these are not necessarily RemoteExceptions. In addition, findByCriteria does not throw an exception. This would work, but won't the client be forced to know the difference between the local and remote interface?
Hi Jason, First, the difference between the vernacular usage of a pattern's name and it's actual definition can get blurry, so don't take my word for any of this: there's a nice article here about it. However, I would say it's an Adapter. Now, to answer the heart of your question. What I suggest is that you have two implementation of the connection interface. A RemoteConnection, and a LocalConnection, and you have a Factory that doles these out to the GUI clients. They're the adapter(sic) that the GUI class will be working with, and they throw GUI friendly exceptions like "GUIRecordNotFoundException", "GUIFatalErrorException", etc. However, they(the Connections), internally, handle the complexity of working with the actual Remote or Local DataImpl. Thus, RemoteConnection might catch a RemoteException, wrap it in a GUIFatalErrorException, and throw it to the client. Similarly, The LocalConnection might catch a plain vanilla IOException, wrap it in a GUIFatalException, and pass it to the GUI.Either way, the GUI never knows, or cares, if it's working remotely or locally. Incidentally, this is a great opportunity to use and learn about Exception chaining. Does that help? All best, M [ July 17, 2003: Message edited by: Max Habibi ] [ July 17, 2003: Message edited by: Max Habibi ]
Thanks for the quick response! I've been giving a lot of consideration to your suggestion, and have developed a tentative plan. (How could one possibly develop such a project without planning? :shudders Let's see: The GUIController requests a connection from the ConnectionFactory. The getLocalConnection returns a LocalConnection (from the db package), and the getRemoteConnection returns a RemoteConnection (from the remote package). The Connection interface (in the db package) provides the same methods as the DBAccess interface, but ADAPTS the signatures to the needs of LocalConnection and RemoteConnection, perhaps by including "throws IOException" in the method signatures. The Connection interface maintains a reference to DBAccess (?). Now, LocalConnection implements Connection directly, whereas RemoteConnection simply extends Connection and Remote. Therefore, DataImpl, which implements RemoteConnection, is allowed to include "throws RemoteException" in its method signatures. It should look something like this: Connection adapts DBAccess LocalConnection implements Connection RemoteConnection extends Connection, Remote DataImpl implements RemoteConnection ConnectionFactory returns Connections (RemoteConnection or LocalConnection) Am I on the right trail? Thanks, Jason