File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes DataAccessFactory Dilemma 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 "DataAccessFactory Dilemma" Watch "DataAccessFactory Dilemma" New topic
Author

DataAccessFactory Dilemma

Aruna Raghavan
Ranch Hand

Joined: May 14, 2002
Posts: 194
Hi,
#1
I used the same DataInterface (extends Remote) to create local/RemoteData classes. Now, since my DataInterface extends Remote, every single method has "throws RemoteExceptions" in the signature. Now, for localmode, it won't throw RemoteExceptions which is probably OK. With this approach, I have three sets of Remote objects - ConnectionFactory, ConnectionInterface and DataInterface.
#2
If I leave DataInterface as just an non-remote interface, things still work because I access the RemoteData through a ConnectionFactory. But, on the client side the DataAccessFactory looks goofy because now it can not access the Remotedata. It gives me exceptions on RemoteData not being 'Serializable'. My understanding is that the Data should not be Serializable due to the presence of RandomAccessFile (I get errors when I do this) also since RemoteData should only reside on the Remote side (hence it should be extending UnicastRemoteObject).
currently I am using #1 from above. But I am not sure if I am overusing the RemoteObjects. Anything wrong with this?
Thanks very much,
Aruna.


Aruna A. Raghavan<br />SCJP, SCJD, SCWCD
Jai Karuppuswamy
Greenhorn

Joined: Jan 22, 2002
Posts: 11
Aruna,
In my implementation, I have two separate interfaces for local and remote data objects.
Try adding a RemoteDataInterface that extends both DataInterface and java.rmi.Remote. The class that implements this RemoteDataInterface can implement java.io.Serializable.
Hope that helps.
Jai.


If everything is under control, you're going too slow.<br /> Mario Andretti
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Originally posted by Jai Karuppuswamy:
The class that implements this RemoteDataInterface can implement java.io.Serializable.
Remote objects don't need to be Serializable, as they will never be serialized from one JVM to another as part of an RMI call. Only non-remote objects involved in an RMI call do need to be serializable.
- Peter
Aruna Raghavan
Ranch Hand

Joined: May 14, 2002
Posts: 194
Jai,
What I was trying to say is- I can't make FBNData serialzable. Try doing this, you will get run time exceptions because RandomAccessFile db.db can not be serialized. If you extend off of UnicastRemoteObject to make sure to not to serialize something. That way, the object stays on the Remote server.
Also, using two interfaces to create RemoteData does not work. Any time you extend Remote, your methods do have to throw RemoteExceptions.
In my approach #1, I am using a common data interface that does extend RMI Remote object. I don't think this is bad. I was just wondering if others also had to have three remote interfaces -
ConnectionFactory, Connection and FBNRemoteData.
Aruna Raghavan
Ranch Hand

Joined: May 14, 2002
Posts: 194
I could consolidate my Connection and DataInterfaces into one. Someone pointed this out in the past but I was having trouble with the concept of a "Connection" interface for a Local client.
Jai Karuppuswamy
Greenhorn

Joined: Jan 22, 2002
Posts: 11
Remote objects don't need to be Serializable

Mmhm. That was an eye opener. For some reason, I have been thinking that remote objects had to be Serializable so that they can be ported over a network.
I changed my remote data object to not implement Serializable, and everything works well.
Thanks for that insight, Peter.
Jai.
Aruna Raghavan
Ranch Hand

Joined: May 14, 2002
Posts: 194
Hi,
I created a DataInterface that has methods that throw generic Exceptions. I inherit LocalData and just handle the IO or database exceptions there.
On the remote side, I have a RemoteDataInterface that extends both DataInterface and Remote. My RemoteDataImpl extends RemoteDataInterface and handles Remote/IO/DB exceptions.
From what I can see, I am ,losing information on a specific type of exception when I call these methods but it looks clean otherwise.
I appreciate your comments very much, thanks.
Aruna.
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Originally posted by Aruna Raghavan:
I created a DataInterface that has methods that throw generic Exceptions.
Yuck. What reason could you possibly have to throw away all exception type information?
- Peter
Aruna Raghavan
Ranch Hand

Joined: May 14, 2002
Posts: 194
Peter,
I can't extend the same DataInterface unless it throws generic exceptions and the implemented Local or Remote Data classes throw the specific exceptions. RemoteData extends both DataInterface and Remote.
The other option was to have DataInterface extend Remote but it didn't make sense to have Remote Exceptions in the LocalData class. This was how I had it originally.
Aruna.
Aruna Raghavan
Ranch Hand

Joined: May 14, 2002
Posts: 194
Peter,
What is exactly the advantage of knowing whether I am catching a RemoteException or DatabaseException rather than just an exception? Being able to give the user a more relevant and meaningful error?
Thanks,
Aruna.
John Smith
Ranch Hand

Joined: Oct 08, 2001
Posts: 2937

What is exactly the advantage of knowing whether I am catching a RemoteException or DatabaseException rather than just an exception? Being able to give the user a more relevant and meaningful error?

This is what many people miss, -- when you catch an exception, you can actually process it. For example, if it is a remote exception, you may retry the request, or display a "Cancel, Retry?" dialog, or offer to connect to a local database, or try an alternative server, or automatically log a network problem, or exit the app (how rude!), or ignore the exception (how common and wrong), or send the user to hell. And if it is a Database exception, again a number of alternative actions is possible (such as restore the database if it is corrupt, or offer a unique key if the attampt is made to add a record with duplicate key). If the caller instead caught a generic Exception, all it could do at that point is to show some (criptic) error to the user. That's why it is critical to differentiate between the exception types.
It is easy to write methods that declare "throws Exception", and one may actually think of it as an "elegant way to not overwhelm the user with the long list of thrown exceptions", but this is simply the abuse of the beautiful language
Eugene.
[ January 06, 2003: Message edited by: Eugene Kononov ]
Aruna Raghavan
Ranch Hand

Joined: May 14, 2002
Posts: 194
Eugene,
I will back to the way I had it originally.
Thanks,
Aruna
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Originally posted by Aruna Raghavan:
What is exactly the advantage of knowing whether I am catching a RemoteException or DatabaseException rather than just an exception? Being able to give the user a more relevant and meaningful error?
In general, different errors are often handled completely differently. Transient transport errors may sometimes be handled by retrying a couple of times, perhaps after a sleep(). System errors are logged and perhaps an administrator is alerted. User errors ("this destination does not exist dumbo") are again handled differently. You don't need such detailed exception handling in the context of this assignment, but that doesn't mean you can let your good practices slip.
In addition, a programmer developing an application against an API, such as your colleague who will reuse the networked database, will want to know what errors can be expected in the first place. Not only that, but (s)he should not be forced to catch and handle exceptions that cannot be thrown at all.
In my career, I have had the misfortune to develop against a couple of APIs that threw a completely amorphous Exception at me, and I loathed them with a passion. It wrecks any sensible exception handling you might otherwise have done. It leaves you completely in the dark about failure modes.
The other extreme, of course, is throws bloat; a throws clause with a dozen different exceptions in it. There are two ways to address that.
  • Make sure your own exceptions form a hierarchy, so you can simply replace a dozen different exceptions by their base class.
  • Where you cannot do this, for example because you have no control over the exceptions (e.g. IOException, SQLException, etc) you can use wrapper exceptions (check out InvocationTargetException for a wrapper exception used by Java reflection).
  • In the assignment, though, you need neither technique.That'd do it. Note that both classes narrow the exception list thrown by the interfaces. Note also that Data is not instanceof Remote.
    - Peter
    Aruna Raghavan
    Ranch Hand

    Joined: May 14, 2002
    Posts: 194
    Peter,
    Shouldn't
    public class Connection implements RemoteDataInterface { public void fooBar() throws DatabaseException { // foobar }}
    be
    public class Connection implements RemoteDataInterface { public void fooBar() throws DatabaseException, RemoteException { // foobar }}
    Peter den Haan
    author
    Ranch Hand

    Joined: Apr 20, 2000
    Posts: 3252
    No
    While the client-side stub does throw RemoteException -- that's why the interface must declare it, otherwise the stub couldn't implement the interface -- our server-side implementation itself never throws RemoteException and shouldn't declare it in the throws clause.
    - Peter
    Aruna Raghavan
    Ranch Hand

    Joined: May 14, 2002
    Posts: 194
    Peter,
    If the interface declares a Remote exception, looks like the class extending it ( in this case, Connection) has to throw the Remote exception. If it is inheritance we are talking about, then the supercalss can declare a superset of exceptions and the subclass can just declare a subset of what the superclass declares.
    I get compile errors in Connection class when I implemented it as you showed-
    "Unreported Exception:java.rmi.RemoteException; must be caught or declared to be thrown..."
    Thanks for being patient.
    Aruna
    Aruna Raghavan
    Ranch Hand

    Joined: May 14, 2002
    Posts: 194
    Looks like the compile error is happening because my Connection class forwards requests to my Data class. Data class implements DataInterface which has methods that throw Remote and any other type of exceptions. Connection only knows the Data as DataInterface, rather than DataImpl.
    So, when my Connection class forwards requests to the DataInterface Object, I get the error about not handling the Remote exceptions being thrown by the DataInterface object.
    Aruna Raghavan
    Ranch Hand

    Joined: May 14, 2002
    Posts: 194
    Yep, once I changed the reference in my Connection object to DataImpl from DataInterface, the compile errors are gone.
    Aruna Raghavan
    Ranch Hand

    Joined: May 14, 2002
    Posts: 194
    Peter,
    This essentially takes out the need to have both RemoteData and LocalData. But the assignment requirement says that I should have two Data implementations, one on the client side and one on the server side. I could still give it them but what's the need for it?
    Thanks,
    Aruna.
    Peter den Haan
    author
    Ranch Hand

    Joined: Apr 20, 2000
    Posts: 3252
    Originally posted by Aruna Raghavan:
    Looks like the compile error is happening because my Connection class forwards requests to my Data class. [...] So, when my Connection class forwards requests to the DataInterface Object, I get the error about not handling the Remote exceptions being thrown by the DataInterface object.
    Indeed. So it isn't because you're implementing an interface throwing RemoteException, but because in your code you are calling something else that itself may throw RemoteException. As you found out, it is perfectly alright for an interface implementation to throw fewer (or narrower) exceptions than the interface specifies.
    This essentially takes out the need to have both RemoteData and LocalData. But the assignment requirement says that I should have two Data implementations, one on the client side and one on the server side.
    And you do have them, only you don't realise it It does not say anywhere that you actually have to write the client-side DataInterface implementation yourself, only that it has to exist and that it will have different constructors. The client-side RMI stub class generated by rmic satisfies all the criteria in the assignment.
    Done it -- passed -- no point deductions.
    - Peter
    Sam O'Neill
    Ranch Hand

    Joined: Nov 25, 2002
    Posts: 57
    I understand the fact that by doing this we no longer have a need for separate LocalData and RemoteData implementations that encase either a Data object or a Connection object respectively as neither implementation now throws RemoteException, but I am missing the part where we then handle RemoteExceptions.
    The stub class throws RemoteExceptions as it must conform to the interface but where are we catching and handling them if not in the implementation class.
    Please excuse me if I am not getting this correctly.
    Regards
    Sam
    Peter den Haan
    author
    Ranch Hand

    Joined: Apr 20, 2000
    Posts: 3252
    Originally posted by Sam O'Neill:
    [...] I am missing the part where we then handle RemoteExceptions.
    Neither implementation throws them. The client-side rmic-generated stub does throw them because of the RMI plumbing that sits behind it. The RemoteExceptions are handled by your client code (i.e. the GUI will pop up a error box or something similar).
    - Peter
    Christian Garcia
    Ranch Hand

    Joined: Jan 29, 2002
    Posts: 77
    Peter,
    Please explain this further:
    And you do have them, only you don't realise it It does not say anywhere that you actually have to write the client-side DataInterface implementation yourself, only that it has to exist and that it will have different constructors. The client-side RMI stub class generated by rmic satisfies all the criteria in the assignment.

    Christian


    Christian
    Peter den Haan
    author
    Ranch Hand

    Joined: Apr 20, 2000
    Posts: 3252
    The requirements state [The client] should include a class that implements the same public methods as the suncertify.db.Data class, although it will need different constructors to allow it to support the network configuration. I will assume you have a DataInterface with all the public methods of Data, and that this interface is implemented both by Data and a server-side remote class I'll call Connection. To use this remote class, you use rmic to generate a stub for it. Then the following is true:
  • The stub is a class that implements the same public methods as the suncertify.db.Data class, as it implements DataInterface.
  • The stub has different constructors to allow it to support the (RMI) network configuration; you may not know what these constructors look like but they are bound to differ from Data's and they are bound to facilitate RMI's internals.
  • The stub satisfies all the criteria stated in the instructions, even though it was generated rather than written --- it doesn't say anywhere that you have to write this class yourself.
  • Does this help?
    - Peter
    [ January 09, 2003: Message edited by: Peter den Haan ]
    Christian Garcia
    Ranch Hand

    Joined: Jan 29, 2002
    Posts: 77
    Peter,
    So, given your explanation all that needs to be done is define a Connection class (as you called it) that implements all of the methods in DataInterface. Once that is done RMIC is run on this class to generate the stub. The stub now contains the "behind the scenes" constructors that satisfy the requirement.
    I'm a confused on this statement, though:
    ..it doesn't say anywhere that you have to write this class yourself.


    Thanks for bearing with me on this.
    CG
    [ January 10, 2003: Message edited by: Christian Garcia ]
    Peter den Haan
    author
    Ranch Hand

    Joined: Apr 20, 2000
    Posts: 3252
    Originally posted by Christian Garcia:
    I'm a confused on this statement, though: "It doesn't say anywhere that you have to write this class yourself."
    The only point I'm trying to make is that many are reading the instructions as You have to write a class that implements the same public methods as the suncertify.db.Data class [...].
    It doesn't say that. It says [The client] should include a class [...]. The instructions don't state, neither implicitly nor explicitly, that you actually have to write that class; in other words, an rmic-generated class satisfies them just as well.
    - Peter
    Christian Garcia
    Ranch Hand

    Joined: Jan 29, 2002
    Posts: 77
    Peter,
    I've defined a RemoteDataInterface that includes the public methods in the Data class, but each throws a RemoteException (via extending Remote).
    How does the 'generated stub' know to implement RemoteDataInterface?
    Peter den Haan
    author
    Ranch Hand

    Joined: Apr 20, 2000
    Posts: 3252
    The rmic tool generates a pretty stupid object that implements the methods declared in the interface by serializing their call arguments and sending the whole caboodle over the wire. At the server end, RMI deserializes everything and dispatches the calls to the "real" RemoteDataInterface implementation that you have written.
    That's RMI in a nutshell, modulo a gazillion minor little details
    - Peter
    Christian Garcia
    Ranch Hand

    Joined: Jan 29, 2002
    Posts: 77
    Got it. I misunderstood the original post. I thought that all that was needed was the RemoteDatInterface without a Class that implements the methods and provides code for each. I guess it would have been "magic" if the latter were true.
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: DataAccessFactory Dilemma