This week's book giveaway is in the OCMJEA forum.
We're giving away four copies of OCM Java EE 6 Enterprise Architect Exam Guide and have Paul Allen & Joseph Bambara on-line!
See this thread for details.
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes NX: Question on Max's DVD project Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCM Java EE 6 Enterprise Architect Exam Guide this week in the OCMJEA forum!
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "NX: Question on Max Watch "NX: Question on Max New topic
Author

NX: Question on Max's DVD project

Manoj Gundawar
Ranch Hand

Joined: Nov 17, 2002
Posts: 169
In the MAX's DVD project, the code listing is as follows:
public interface DBClient {
(methods decleared here do not throw RemoteExceptions)
}
Then there is another interface created for the RMI (remote) package:
public interface DVDDatabaseRemote extends Remote, DBClient {}
The class DVDDatabaseImpl in the remote package is decleared as:
public class DVDDatabaseImpl extends UnicastRemoteObject implements
DVDDatabaseRemote {

Now the DBClient methods implemented in this class throws the RemoteException, where as the methods decleared in the interface dont.
How is this possible?
Why does it not give a compile time error,as the overridden methods (methods decleared in the interface) do not throw this exception??
If I try to implement interface method in the class, I get compile time error if class's method's throw the RemoteException and Interface method is not decleared to throw that exception.
Please help.
Thanks,
Manoj
[ October 20, 2003: Message edited by: Jmannu gundawar ]

Manoj<br />SCJP, SCJD, SCWCD, IBM WSAD.
Ramses Tutoli
Greenhorn

Joined: Sep 05, 2003
Posts: 26
I think the DBClient methods throw IOException, which is a parent of RemoteException.
Originally posted by Jmannu gundawar:
In the MAX's DVD project, the code listing is as follows:
public interface DBClient {
(methods decleared here do not throw RemoteExceptions)
}
Then there is another interface created for the RMI (remote) package:
public interface DVDDatabaseRemote extends Remote, DBClient {}
The class DVDDatabaseImpl in the remote package is decleared as:
public class DVDDatabaseImpl extends UnicastRemoteObject implements
DVDDatabaseRemote {

Now the DBClient methods implemented in this class throws the RemoteException, where as the methods decleared in the interface dont.
How is this possible?
Why does it not give a compile time error,as the overridden methods (methods decleared in the interface) do not throw this exception??
If I try to implement interface method in the class, I get compile time error if class's method's throw the RemoteException and Interface method is not decleared to throw that exception.
Please help.
Thanks,
Manoj
[ October 20, 2003: Message edited by: Jmannu gundawar ]
Manoj Gundawar
Ranch Hand

Joined: Nov 17, 2002
Posts: 169
Thanks Ramses. That was simple. I didnt notice that. I was in a certain mindframe.
Now the problem I am facing related to this:
Sun's provided interface methods dont throw IOException or even RemoteException. I need to use this for Data class which implement the given interface. This class will be used as Remote object. But it needs to throw remoteException. How can I do that without modifying Sun's interface?
Nowhere SUN has mentioned that I can not modify the interface. But in many of the forums here, it has been said that the interface can not be modified.
I dont see any solution to this riddle.
Can you suggest me something?
Thanks,
Manoj
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
You can create Remote version of the interface which is just like the provided interface except all methods also throw RemoteException. This class can't actually extend the DB interface, but it's very similar. Then create another class which is a RemoteDBAdapter, which does implement DB and contains a RemoteDD inside it. Basically this class just forwards all calls to the contained instance, but catches any RemoteException and does something with it. (Probably the same thing that you do with any IOException which was thrown inside the Data class.) The adapter is one extra layer, but it converts the RemoteDB which RMI requires to the DB which your assignment requires.


"I'm not back." - Bill Harding, Twister
Manoj Gundawar
Ranch Hand

Joined: Nov 17, 2002
Posts: 169
Thanks JIM,
Great. This will solve my problem. Thanks again.
But just a question which I have in mind for a long time. Is it ok to follow the model more or less similer to DVD project? Do Sun know about this book and the model followed by that sample project.
Cause I have seen many postings where ppl are following the same GUIcontroller and Remote models followed by DVD project.
I was little skeptical and wanted to create something which wont be like copycat of this sample project.
I am not aware, if anyone has been questioned so far about his model's relation to the DVD model
Thanks,
Manoj
Andrew Monkhouse
author and jackaroo
Marshal Commander

Joined: Mar 28, 2003
Posts: 11437
    
  85

Hi Manoj,
I think it should be OK. Max's DVD application is similar in scope to the SCJD assignments, but not the same. So you cannot just copy the code - you have to read what Max has presented, understand it, and adapt it to your assignment.
In that respect it is no different than if you copied a design mentioned here in JavaRanch, or from one of the many tutorials on the Sun web site.
Regards, Andrew


The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
I think the key is to make sure that whatever you do, it fits the instructions you have. Sun knows about Max's book, but doesn't seem too concerned, because their assignment is different enough that you will be forced to adapt things anyway, and you can only do this by making your own decisions. Many parts will end up very similar to Max's design; others will be completely different. I wouldn't worry much about the parts that are similar, as long as your code meets the specifications. Though of course you shouldn't copy any code directly from Max's book either.
[ October 20, 2003: Message edited by: Jim Yingst ]
Manoj Gundawar
Ranch Hand

Joined: Nov 17, 2002
Posts: 169
Andrew and Jim,
Thanks for your suggestions.
I love this place. Without this forum, it would have taken long time to resolve critical doubts.
Thanks,
Manoj
Manoj Gundawar
Ranch Hand

Joined: Nov 17, 2002
Posts: 169
Hi Jim,
This was your reply to my question:
----------------------------------------
You can create Remote version of the interface which is just like the provided interface except all methods also throw RemoteException. This class can't actually extend the DB interface, but it's very similar. Then create another class which is a RemoteDBAdapter, which does implement DB and contains a RemoteDD inside it. Basically this class just forwards all calls to the contained instance, but catches any RemoteException and does something with it. (Probably the same thing that you do with any IOException which was thrown inside the Data class.) The adapter is one extra layer, but it converts the RemoteDB which RMI requires to the DB which your assignment requires.
--------------------------------------------
When I re thought about this, I got little confused. Can you draw a small picture here? or can you provide class declarations line, which shows the implementation of the above design.
One more doubt I have is, as the remote DB object implements the new interface (which is defined for the RemoteException) I wont be able to cast the localconnection and remoteconnection objects to the common interface, as they both implement different interfaces.
This will cause some desing issues at the client side while making calls.
Your response will be greatly appriciated.
Thanks,
manoj
[ October 24, 2003: Message edited by: Jmannu gundawar ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Here are some simple classees following the pattern I'm talking about.

The Foo and RemoteFoo interfaces are certainly similar, but a RemoteFoo is not a Foo, and can't be, because RMI will end up requiring the RemoteFoo to be able to throw exceptions which a Foo may not throw. So, we can use a RemoteFooAdapter to convert a RemoteFoo to act like a Foo. This means you have to catch any RemoteExceptions and handle them somehow. The simplest thing I came up with is to throw a RuntimeException, though there are other strategies possible.
Hope that helps...
Manoj Gundawar
Ranch Hand

Joined: Nov 17, 2002
Posts: 169
Hi Jim,
Thanks for the sample code.
But I guess I am too dumb to move forward. I tried to implement this design (in fact the same sample code) But I faced following doubts which are stopping my further progress:
1. It seems I have to bind the object of type RemoteFooImpl. But as this implements RemoteFoo, I can not cast this to a commen interface in my factorymethods, where I get the instance based on the connection type chosen. For ex, I can not have methods something like this:
public static Foo getRemote (this is not possible as the remote object will be of type RemoreFoo and not the Foo)
public static Foo getLocal (Although this is possible)

2 Second doubt is how to use RemoteFooAdapter. As it seems it is only created to be used during network mode, but the object that is bound is of type RemoteFooImpl and not the RemoteFooAdapter. So what is the ues of RemoteFooAdapter?
I can not bind the object of type RemoteFooAdapter as it does not extend UnicastRemoteObject.
Your further clarification is highly appriciated.
Thanks in advance.
Manoj
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
1. It seems I have to bind the object of type RemoteFooImpl.
Well, there are other more elaborate ways (e.g. binding a separate factory object) but yes, binding a single RemoteFooImpl on the server is simplest, and all you really need. (Unless you want to follow the connection factory pattern, but that can come later.)
For ex, I can not have methods something like this:
public static Foo getRemote (this is not possible as the remote object will be of type RemoreFoo and not the Foo)


Exception handling is omitted, depending how & where you want to handle that.
Bharat Ruparel
Ranch Hand

Joined: Jul 30, 2003
Posts: 493
Hello Jim,
You wrote:

The Foo and RemoteFoo interfaces are certainly similar, but a RemoteFoo is not a Foo, and can't be, because RMI will end up requiring the RemoteFoo to be able to throw exceptions which a Foo may not throw. So, we can use a RemoteFooAdapter to convert a RemoteFoo to act like a Foo. This means you have to catch any RemoteExceptions and handle them somehow. The simplest thing I came up with is to throw a RuntimeException, though there are other strategies possible.

You show this in your code snippet as follows:

My design is exactly same as yours. Except that I am simply logging the exception as shown in the following snippet:

You are throwing a CustomRuntimeException here. Would you care to elaborate a bit on it?
The things that will interest me are:
1. What do you call this exception?
2. Do you use exception chaining facility to chain it for your GUI client?
3. Is there a specific message that you attach to it?
If you will give an example, I will greatly appreciate it.
By the way, what you call RemoteFooImpl, I called RemoteDBAdapter in my implementation and your RemoteDBAdapter I called ClientDBAdapter. My logic for naming them in this manner was: my RemoteDBAdapter sits on the server side of the network and adapts the Data (or DataAdapter) for the network communication. The ClientDBAdapter sits on the client side of the network and adapts the Data (or DataAdapter) for the client factoring out the remote communication problems/issues.
Other than that, the design is the same.
Thanks.
Bharat


SCJP,SCJD,SCWCD,SCBCD,SCDJWS,SCEA
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Regarding what to do with the RemoteException: to me, it's basically the same question as, what do you do if there's an IOException during a mehtod like update() which isn't allowed to throw IOException? (Since the goal here is to adapt the RemoteFoo interface to fit inside the Foo interface which doesn't declare IOExceptions. Whatever you do inside your Data class for an IOException, I'd do the same thing inside RemoteDataAdapter (or whatever we're calling it) for a RemoteException. In my case, I definitiely want to throw some kind of exception, so that the caller knows that the method failed. The choices are - use one of the allowed checked exceptions, or use an unchecked exception. Well, the checked exceptions allowed in my DB interface are RecordNotFoundException and DuplicateKeyException. The latter in particular is an exceedingly bad name for a problem caused by an IOException, and since there's at least one method which can throw DKE but not RNFE, I refuse to use a DKE to wrap an IOException. I prefer to just wrap all IOExceptions in a different exception, which necessarily must be a RuntimeException subclass.
1. What do you call this exception?
DBAccessException
2. Do you use exception chaining facility to chain it for your GUI client?
Absolutely.
3. Is there a specific message that you attach to it?
Depends on the situation, but usually not. Generally all the info I need is in the stack trace. The general meaning of a DBAccessException is "whatever you were trying to do, it didn't work." Generally I use
dbae.getMessage() + "\n\nCause: " + dbae.getCause().toString()
as a short error message that can be displayed to the user, as it's friendlier than a stack trace, but I can't anticipate all the strange sources of IOExceptions that might occur, other than FileNotFoundException. Other than that, the user just sees "Sorry, it didn't work" along with whatever the RemoteException toString() spits out. If I have a good custom message at the time I first catch the IOException or RemoteException, I include it in the new exception.
Regarding class names - well of course I was changing class names around here, as I didn't want to just dump a bunch of actual working assignment code here in the forum. In this post I was more lazy and used the "real" names more often. But our names are actually pretty similar.
Bharat Ruparel
Ranch Hand

Joined: Jul 30, 2003
Posts: 493
Thanks Jim,
Appreciate your response.
Regards.
Bharat
Manoj Gundawar
Ranch Hand

Joined: Nov 17, 2002
Posts: 169
Hi Jim,
Thanks for all the low-level details of this approach. It is really useful. I just have one more question. (Probably)
As this design looks quite complicated, is this a standard way of solving such kind of problems? Does this pattern have any name? I just want to know, if this design pattern fits in any defined design pattern.
Thanks,
Manoj
Bharat Ruparel
Ranch Hand

Joined: Jul 30, 2003
Posts: 493
Hello Manoj,
We should wait to hear from Jim. As far as I know, this is an example of the adapter pattern. It could be a mediator pattern as well. May be Andrew will respond too?
Regards.
Bharat
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
The RemoteFooAdapter is an adapter, yes. We want one interface, Foo, and instead we have an incompatible interface, RemoteFoo, so we use an adapter to convert one to another.
As for other parts - well let's see. The Foo interface was imposed by the requirements. (Not everyone agrees that we necessarily have to have a Foo appear on the client side, but I think it's a reasonable interpretation of the requirements, and encourages reuse of components which are desiged to work with Foo instances.) The RemoteFoo interface and the RemoteFooImpl classes are standard for RMI if you want to make a remote object accessible from multiple machines. The RemoteExceptions in the signature are essentially forced on us by RMI. If the original Foo interface had allowed RemoteExceptions, we might have simplified by letting Foo and RemoteFoo be the same interface, and also FooImpl and RemoteFooImpl could have been the same class. But since the requirements didn't allow this, we needed two interfaces, and two implementations. The requirements also say that in local mode no networking code is to be used. To me this implies that FooImpl shouldn't use any networking code at all; keep that in a separate class.
I suppose if we want to give names to these patterns they're the RMI remote proxy pattern, and the "design for interfaces" pattern. These may have more formal names in the patterns community. As you can tell, I don't always pay attention to the standard terms for things.
Andrew's busy today, and Mark S may be too. But we've usually got a number of other folks floating around here with worthwhile comments...
[ October 27, 2003: Message edited by: Jim Yingst ]
Manoj Gundawar
Ranch Hand

Joined: Nov 17, 2002
Posts: 169
Thanks Jim,
I am not sure why, but your answers sound always convincing!! Now I think this pattern has evolved naturally in the given circumstances. So it need not even have name..
And now I also know what is the bottom line(ha ha) It says:
"I have a catapult. Give me all the money, or I will fling an enormous rock at your head."
Thanks,
Manoj
Andrew Monkhouse
author and jackaroo
Marshal Commander

Joined: Mar 28, 2003
Posts: 11437
    
  85

Originally posted by Jmannu gundawar:
And now I also know what is the bottom line(ha ha) It says:
"I have a catapult. Give me all the money, or I will fling an enormous rock at your head."

Very good.
But you forgot to translate the Iacomus Iuvencissimus tag at the end
(The MD forum does have value - it teaches us new things :roll: )
Regards, Andrew
Stephen Galbraith
Ranch Hand

Joined: Oct 27, 2003
Posts: 90
Hi,
just been reading this thread. Interesting.
I was wondering if this approach could work...
As I understand it we are free to generate our RecordNotFoundException, which we could make extend IOException - after all, it sounds like a type of IOException.
RemoteException also extends IOException.
Therefore we can write one adapter, DBAdapter, which throws IOException where appropriate instead of either RNFE or RemoteException. And hence both the RemoteClient and LocalClient could implement the same interface removing the need for an adapter for the remote and a separate adapter for the local (and making a nice little factory class to return a connection of the correct type).
Comments please!


SCJP 1.4, SCJD, SCWCD 1.4
Philippe Maquet
Bartender

Joined: Jun 02, 2003
Posts: 1872
Hi Stephen,
Just been reading your post. Interesting.
As I understand it we are free to generate our RecordNotFoundException, which we could make extend IOException - after all, it sounds like a type of IOException.
RemoteException also extends IOException.
Therefore we can write one adapter, DBAdapter, which throws IOException where appropriate instead of either RNFE or RemoteException. And hence both the RemoteClient and LocalClient could implement the same interface removing the need for an adapter for the remote and a separate adapter for the local (and making a nice little factory class to return a connection of the correct type).

Looks nice ! And as, from memory, it's the first time that idea arises, you should be able to copyright it.
Yes, it seems interesting to make RecordNotFoundException an IOException. BTW, it would the same for DuplicateKeyException.
Best,
Phil.
Stephen Galbraith
Ranch Hand

Joined: Oct 27, 2003
Posts: 90
Hi Philippe,
Just been reading your reply. Interseting!
Glad you like it! I think it also deals with the exception chaining stuff as well, so cleans up some of that discussion as well.
My project doesn't declare a DuplicateKeyException. Could you really argue that DuplicateKey is an IOException.
Maybe you could
Philippe Maquet
Bartender

Joined: Jun 02, 2003
Posts: 1872
Hi Stephen,
My project doesn't declare a DuplicateKeyException. Could you really argue that DuplicateKey is an IOException.
Maybe you could

I like consistency over everything else regarding exceptions. So as I liked your reasoning about RNFE, if seemed natural to me to do the same with DuplicateKeyException. If you think that Data belongs to some broad "IO domain", it makes sense IMO that all checked exceptions thrown by Data methods would extend IOException.
But the big problem is that there is no perfect solution in that area given the DBAccess interface provided.
Many people here suggest to wrap Data IOExceptions in the provided checked exceptions. Their main argument is that they hate RuntimeTimeExceptions. Either do I, though I chose to wrap them in some DBException extending RuntimeException, just for consistency :
  • findByCriteria() doesn't throw any exception, so it doesn't provide any IOException possible wrapper
  • If you may defend that DuplicateKeyException would be an IOException, the contrary is hard to defend : in createRecord(), throwing DuplicateKeyException because of an IOException caused by some disk failure would be misleading IMO. Same reasoning may be applied to RNFE BTW.


  • Above, I criticized the provided DBAccess interface. Another example of exceptions hole is the missing DuplicateKeyException in updateRecord(). If createRecord() may throw a DuplicateKeyException, updateRecord() should at least throw a similar exception in case some change of the primary/unique key creates a duplicate key ...
    Best,
    Phil.
    Stephen Galbraith
    Ranch Hand

    Joined: Oct 27, 2003
    Posts: 90

    I like consistency over everything else regarding exceptions. So as I liked your reasoning about RNFE, if seemed natural to me to do the same with DuplicateKeyException. If you think that Data belongs to some broad "IO domain", it makes sense IMO that all checked exceptions thrown by Data methods would extend IOException.

    Okay, convinced. DuplicateKeyException should extend IOException.

    findByCriteria() doesn't throw any exception, so it doesn't provide any IOException possible wrapper

    I can't see this my URLyBird 1.3.1. There's just a find(String[] criteria) which does throw RNFE. Maybe I need to read it more carefully

    If you may defend that DuplicateKeyException would be an IOException, the contrary is hard to defend : in createRecord(), throwing DuplicateKeyException because of an IOException caused by some disk failure would be misleading IMO. Same reasoning may be applied to RNFE BTW.

    Agreed. This would be misleading. But doesn't the SUN instructions force us down this route?
    Stephen Galbraith
    Ranch Hand

    Joined: Oct 27, 2003
    Posts: 90
    I suppose the Data class could do the following

    and we'd still throw the IOException if an IOException occurred and a RNFE if one of them occurred. We still implement the interface DBMain.
    Philippe Maquet
    Bartender

    Joined: Jun 02, 2003
    Posts: 1872
    Hi Stephen,
    Unfortunately it will never compile, because you must obey the same rule when implementing a method as you do when overriding one : not throw newer or broader exceptions.
    Best,
    Phil.
    Stephen Galbraith
    Ranch Hand

    Joined: Oct 27, 2003
    Posts: 90
    Ooops!
    Jim Yingst
    Wanderer
    Sheriff

    Joined: Jan 30, 2000
    Posts: 18671
    But doesn't the SUN instructions force us down this route?
    Not exactly. The instructions force us to choose between several undesireable alternatives - it's a question of which you think is least offensive to your sensibilities. Personally I prefer to throw an unchecked exception rather than a checked exception with a misleading (that is, completely incorrect) name. Especially since I'd need to use two different checked exceptions for this purpose, plus in find() I can't use any checked exception, so there's no way to be consistent here while using checked exceptions. But others have slightly different APIs to implement, and different ideas of the importance of using checked exceptions. I don't believe there's any final answer to this; you canget a good score with either solution if you justify it well in choices.txt.
    Stephen Galbraith
    Ranch Hand

    Joined: Oct 27, 2003
    Posts: 90
    Thanks everyone, that's great.
    I think I'll use Errors rather than checked exceptions in the Data class to handle the other exceptions. I too am not too happy with creating an exeption with a misleading name (almost as bad as catching generic exceptions ) so I guess the unchecked route is the other way.
    As for on the Client side, I think I'll have my Adapter throwing IOExceptions and have the DuplicateKeyException (which I found on a re-re-re-read!) and RecordNotFoundException both extend IOException.
    Thanks,
    Steve
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: NX: Question on Max's DVD project