This week's book giveaway is in the Mac OS forum.
We're giving away four copies of a choice of "Take Control of Upgrading to Yosemite" or "Take Control of Automating Your Mac" and have Joe Kissell on-line!
See this thread for details.
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes Design issues with local-remote Data class Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "Design issues with local-remote Data class" Watch "Design issues with local-remote Data class" New topic
Author

Design issues with local-remote Data class

Vivian Richards
Greenhorn

Joined: Jun 19, 2001
Posts: 7
Hi,
I am very confused with the local-remote Data classes implementation. I went through some of the other messages in the discussion board but it didn't help me.
My initial design looks like this:
interface DataInterface
{
//all the public methods of Data class
}
class LocalDataClient implements DataInterface
{
protected Data data;
//All the methods calls are delegated to the Data class
}
class RemoteDataClient extends UnicastRemoteObject implements DataInterface
{
protected Data data;
//All the methods calls are delegated to the Data class
}
class DataAccessor
{
DataInterface dataObj;
//Using polymorphism, at runtime, based on local or remote
dataObj = new LocalDataClient() or
dataObj = new RemoteDataClient()
}
Questions:
1. Please comment on this design. Is it right ?
2. Should the DataInterface extend Remote. In that case , should all the methods in LocalDataClient throw RemoteException eventhought they are not going to do any RMI calls ?
Thanks in advance.
Rick Fortier
Ranch Hand

Joined: Jun 04, 2001
Posts: 147
My DBInterface extends Remote. Some methods throw only RemoteException, others RemoteException and DataException.
My Data class implements DBInterface and methods throw IOException and DatabaseException.
In order to not duplicate code, the client must be able to use the Data class when in local mode. It also must be able to use the DBInterface class when in remote mode. But since there is a mixture of Exception types, the client gui could look really messy.
I chose to use the Adaptor pattern with the Factory pattern to create a services layer. I call it my FlightServices layer. I also did not like the idea of the gui having intimate knowledge of the Data class.
My overall structure are these layers:
  • Gui
  • FlightServices
  • RemoteInterface
  • Data

  • I let my gui only do what it does best, display data and get input from the user. My gui has no idea where the data is or how to do locks/unlocks, or how to sort through all of the various exception types.
    My FlightServices layer presents a generic set of reservation methods: Connect, LookupFlight, BookFlight, SearchFlight, GetCitiesList, etc... This layer instantiates the correct object for local and remote and stores this object locally. When the client makes the call, this layer knows how to interface with the Data layer. So inside BookFlight it does the lock, read, update, unlock logic. And it only throws FlightServicesExceptions back to the gui layer. So this layer has no idea how to display things to the user, or how to read data out of the file.
    My Data layer only receives calls from the FlightServices layer. The only thing it knows how to do is deal with the physical file. It does not know anything about locking or unlocking either. Since the lock/unlock methods must be used while in Remote or Local mode, it did not make any sense to implement them in Data.
    On the server, I have a class called FBNStart which binds my FBNServer to the registry.
    When FBNServer is started, it instantiates the Data object and passes all calls through to Data and to my LockManager class.
    It is sole purpose to open the database and pass through all calls to other objects. Well, it also has a Timer running which periodically looks for stale locks.
    My LockManager class was created because I did not want to mess with locks when the program was run in local mode. So this singleton class handles all of the locking logic. So whenever FBNServer gets a lock or unlock call, it passes through to LockManager, not Data.
    Let me tell you some good reasons to have a FlightServices layer.
    • You can write nonGUI clients and do load testing of your server. This would be difficult to do with all of the logic embedded in the Gui class.
    • It is alot easier to debug. You can see what the data looks like alot easier.
    • In a real world environment, you can more easily divide the work amongst your team. One guy does gui, one FlightServices, and one Server.
    • You can much more easily change or upgrade the gui.
    • Eventually you can move it to the server, where it belongs, without changing your gui. And then it would make a nice interface for web enablement.

    • Hope this wasn't too much.
      [This message has been edited by Rick Fortier (edited June 19, 2001).]
Vivian Richards
Greenhorn

Joined: Jun 19, 2001
Posts: 7
Hi Rick,
Thanks for the very detailed reply. It was very helpful. Based on your design I have a few more doubts. Hope you would find time to answer them.
1. Can you change the class definition of Data class provided by Sun and the method singatures ? This needs to be done if you have your Data class implementing the DBInterface.
2. Just for clarification, you have a remote FBN server that would contain Data class and all calls to the FBN server are delegated to the Data class. Am I right ?
Thanks once again.
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Originally posted by Rick Fortier:
My DBInterface extends Remote. Some methods throw only RemoteException, others RemoteException and DataException.
My Data class implements DBInterface and methods throw IOException and DatabaseException.

This implies that <code>Data instanceof Remote</code>, even though it is not a remote object at all. This breaks the <code>Remote</code> contract. IMHO, better strip the <code>Remote</code> out of <code>DBInterface</code>, and add a <code>DBRemoteInterface extends DBInterface, Remote</code>.
- Peter
Rich Wardwell
Ranch Hand

Joined: Jan 20, 2000
Posts: 33
Originally posted by Peter den Haan:

This implies that <code>Data instanceof Remote</code>, even though it is not a remote object at all. This breaks the <code>Remote</code> contract. IMHO, better strip the <code>Remote</code> out of <code>DBInterface</code>, and add a <code>DBRemoteInterface extends DBInterface, Remote</code>.
- Peter


That would be a good solution if you could extend two interfaces.
Alternatively, you could create a class that implements both interfaces and then delegate all of your calls to Data class, but that doesn't seem very appropriate either.

<B>Rich Wardwell</B><BR> <A HREF="mailto:rcw3@levelpath.com" rel="nofollow">rcw3@levelpath.com</A> <BR>Sun Certified Programmer for the Java 2 Platform
Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
There�s something I don�t quite understand. If you don�t want Data to be instanceof remote, and make it instanceof DBInterface, that sounds good. But when trying to make a DBRemoteInterface extending DBInterface, and Remote, you must remember to make all you declared methods throw a RemoteException. If this wasn�t stated in the superinterface, you will not be able to add the RemoteException in the signatures of the methods declared in the DBRemoteInterface...
I hope I was somewhat clear,
Benjam�n
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Originally posted by Benjam�n Amodio:
But when trying to make a DBRemoteInterface extending DBInterface, and Remote, you must remember to make all you declared methods throw a RemoteException. If this wasn�t stated in the superinterface, you will not be able to add the RemoteException in the signatures of the methods declared in the DBRemoteInterface...

Yes, and this is entirely appropriate. After all, an application using DBInterface will have to cater for possible failures of remote communication, while remaining completely agnostic about what version of the database it is using at any particular time.
Note that the implementation can always throw fewer exceptions - the Data class as-is would be a perfectly fine implementation of DBInterface.
- Peter
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Originally posted by Rich Wardwell:

That would be a good solution if you could extend two interfaces.

But you can. See the JLS, 9.1.2.
- Peter

ruilin yang
Ranch Hand

Joined: Feb 25, 2001
Posts: 334
For simplicity, I would only write a wrap class (wrap data class)for network mode. This class will extends UnicastRemoteObject and implement the remote interface.
For the local model, let the client dirrectly access the data class.
This is the most simple approach. It saves a lots trouble for interfaces etc.
Why not ? please comment
Ruilin
Rich Wardwell
Ranch Hand

Joined: Jan 20, 2000
Posts: 33

But you can. See the JLS, 9.1.2.
- Peter

Well how about that... learn something new everyday! :-)

[This message has been edited by Rich Wardwell (edited June 21, 2001).]
Rich Wardwell
Ranch Hand

Joined: Jan 20, 2000
Posts: 33
Originally posted by Peter den Haan:

This implies that <code>Data instanceof Remote</code>, even though it is not a remote object at all. This breaks the <code>Remote</code> contract. IMHO, better strip the <code>Remote</code> out of <code>DBInterface</code>, and add a <code>DBRemoteInterface extends DBInterface, Remote</code>.
- Peter

Ok... so you can extend two Interfaces. What's going to implement DBRemoteInterface? Data? I assume you're going to have to create a whole new delegate class that implements DBRemoteInterface but just calls Data. Of course, I guess you would have to do that anyway.
If DBInterface *STILL* has to throw RemoteExceptions, then what did this buy you? Data implements DBInterface and doesn't throw RemoteExceptions. Wasn't this the original reason you suggested this in the first place? Doesn't this imply that Data is an instanceof Remote? Maybe not in official "type" but at least in interface? I guess that in and of itself might be more appropriate, so I think I can see your point.

[This message has been edited by Rich Wardwell (edited June 21, 2001).]
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Originally posted by Rich Wardwell:
What's going to implement DBRemoteInterface? Data? I assume you're going to have to create a whole new delegate class that implements DBRemoteInterface but just calls Data. Of course, I guess you would have to do that anyway.

Data would implement DBInterface.
What I did personally is create a server-side UnicastRemoteObject implementing DBRemoteInterface. This class (DBConnection) represented a client connection. This set-up achieves the following.

  • The client-side stub implements DBRemoteInterface and thereby DBInterface. In other words, it is exactly the remote version of Data that the application needs to use in networked mode.
  • The DBConnection class delegates most calls directly to the server-side Data class, except for lock and unlock calls, those are delegated to the lock manager. (The locking methods in the Data class itself can be empty stubs.)
  • The "how do I identify my clients" question is solved in a very straightforward way, plus:
  • RMI garbage collection will clean up dead client connections and their locks, virtually for free.

  • If DBInterface *STILL* has to throw RemoteExceptions, then what did this buy you? Data implements DBInterface and doesn't throw RemoteExceptions. Wasn't this the original reason you suggested this in the first place?

    No. The reason was that Data should not be instanceof Remote (look up the contract for the Remote interface in its javadoc).
    It is perfectly valid that the DBInterface methods throw a RemoteException, because DBInterface specifies an interface to a database that may be remote. A client calling a DBInterface should expect RemoteExceptions.
    Doesn't this imply that Data is an instanceof Remote?

    Not at all. The local implementation of this interface, Data, would of course not have the "throws RemoteException" method signature! Data as-is would be a fine implementation of DBInterface.
    - Peter

    [This message has been edited by Peter den Haan (edited June 22, 2001).]
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Originally posted by ruilin yang:
Why not ? please comment

Your client would be full of:

which is really yucky.
- Peter
Trevor Dunn
Ranch Hand

Joined: Jun 13, 2001
Posts: 84
Instead of having your DBInterface class throw RemoteException, which is pretty specific for Remote calls, have them throw IOExceptions, that way when you extend DBInterface to make the RemoteDBInterface the RemoteExceptions will still work and there is no confusion as to why something that is not remote throws a RemoteException.
Just a thought
Trevor
 
Don't get me started about those stupid light bulbs.
 
subject: Design issues with local-remote Data class