Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
kktec<br />SCJP, SCWCD, SCJD<br />"What we observe is not nature itself, but nature exposed to our method of questioning." - Werner Heisenberg
The other approach, assuming you don't want the DBServices methods to throw IOException, is to simply define RemoteDBServices to extend Remote. In that case you will have to define a set of similar methods for RemoteDBServices.
Having done that, on the client side, you would still have to solve the problem of adapting the stub so that your client code can use either it or a direct DBServices implementation.
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
Won't I just be able to catch the DataAccessException on the client GUI side either way?
kktec<br />SCJP, SCWCD, SCJD<br />"What we observe is not nature itself, but nature exposed to our method of questioning." - Werner Heisenberg
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
kktec<br />SCJP, SCWCD, SCJD<br />"What we observe is not nature itself, but nature exposed to our method of questioning." - Werner Heisenberg
Well, DBServices can't but what interface does RemoteDBServicesImpl implement?
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
kktec<br />SCJP, SCWCD, SCJD<br />"What we observe is not nature itself, but nature exposed to our method of questioning." - Werner Heisenberg
What would you have to do if RemoteDBServices does NOT extend DBServices ?
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
...Having done that, on the client side, you would still have to solve the problem of adapting the stub so that your client code can use either it or a direct DBServices implementation.
kktec<br />SCJP, SCWCD, SCJD<br />"What we observe is not nature itself, but nature exposed to our method of questioning." - Werner Heisenberg
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
Hey bro. You got me with all these funky questions of yours...
How would I adapt it to use the same interface?
kktec<br />SCJP, SCWCD, SCJD<br />"What we observe is not nature itself, but nature exposed to our method of questioning." - Werner Heisenberg
I think it's better to take a que from Socrates rather than spoil all your fun by handing you an answer.
From the classic GoF Design Patterns book (you do have it, don't you ?):
Adapter
Intent: Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
Think composition and delegation and you should be able to roll your own quite easily.
Well actually, 5-6 hrs. usually does it for me here in the frozen tundra of Wisconsin (FMAO).
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
kktec<br />SCJP, SCWCD, SCJD<br />"What we observe is not nature itself, but nature exposed to our method of questioning." - Werner Heisenberg
Sounds like you have a temporary case of the "Problem Overload Brain Block" disease.
...the answer will magically appear in your mind.
Oh yeah, and I recommend you do yourself a favor and get the book. All of the patterns and possible solutions described are worthy of deep study.
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
Java Developer
SCJP, SCJD, SCWCD, SCBCD
... solved it by making my database exception extend IOException
kktec<br />SCJP, SCWCD, SCJD<br />"What we observe is not nature itself, but nature exposed to our method of questioning." - Werner Heisenberg
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
And a DataAccessException is not just from an IOException.
For instance, I don't feel it's elegant to just give the client a DataAccessException when it's actually a RecordNotFoundException.
1. Have all the Services interface methods throw Exception + whatever specific checked exception needed for each individual methods (maximal design)
2. Have all the Services interface methods throw RemoteException + whatever specific checked exception needed for each individual methods (minimal design)
3. Have all the Services interface methods throw IOException + whatever specific checked exception needed for each individual methods (the mid-path design)
Handling exceptions (checked and unchecked) appropriately at the gui side:- one way is to handle all the checked exceptions individually, and for the remaining Runtime exceptions (incl DataAccessException) and RemoteException, have a catch (Exception e) block to handle them.
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
I don't know if this work, but try making an interface RemoteDBServices that extends DBServices and Remote and have your RemoteDBServicesImpl implements RemoteDBServices.
Then see if DBServices dbServices = (DBServices)Naming.lookup(url); works.
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
From the classic GoF Design Patterns book (you do have it, don't you ?):
Adapter
Intent: Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
Think composition and delegation and you should be able to roll your own quite easily.
kktec<br />SCJP, SCWCD, SCJD<br />"What we observe is not nature itself, but nature exposed to our method of questioning." - Werner Heisenberg
Originally posted by Derek Canaan:
Hi Jacques,
I'm thinking about the same issues as you. I thought of 3 ways one can retain this "nice-trick" design even though the Data methods throw DataAccessException (= a Runtime Exception, is this so?):
1. Have all the Services interface methods throw Exception (maximal design)
2. Have all the Services interface methods throw RemoteException (minimal design)
3. Have all the Services interface methods throw IOException (the mid-path design)
In a way, the Services interface design is "forced" because:
1. You want Services interface to be used in both alone and networked mode.
2. The methods in the networked mode have to throw RemoteException
So methods in Services have no choice but to throw RemoteException or its superclass. So the 3 solutions should work.
You could do one of these:
1. Unwrap your DataAccessException in book() that wrapped IOException from Data and re-throw it as IOException to make design looked "natural". I think Ken did this (Ken, am i right?)
2. Don't unwrap. Is there any benefits in unwrapping the IOX and re-throwing it?
If i'm not mistaken, Ken's design uses cache. Search method for cache design does not throw any IOException. So even though the search() method in Services throw IOException, it is never thrown in ServicesImpl's search(). This makes the Services design "unnatural", but what choice do you have if you want it to be used in both alone and networked mode.
Ken, is the analysis right? Comments, anyone?
rgds,
derek
[ January 29, 2004: Message edited by: Derek Canaan ]
kktec<br />SCJP, SCWCD, SCJD<br />"What we observe is not nature itself, but nature exposed to our method of questioning." - Werner Heisenberg
...I can see my series of questions wasn't very effective.
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
Isn't the wrapping on the server side also basically an adaptor pattern?
And also, should my ServiceAdaptor used on the gui side to turn RemoteDBServices back into DBServices be in my gui package, or in my db package. It is currently in gui.
kktec<br />SCJP, SCWCD, SCJD<br />"What we observe is not nature itself, but nature exposed to our method of questioning." - Werner Heisenberg
Since its purpose is to be a helper to the gui code, I think that is a reasonable choice except that it places a dependency on rmi into the gui package. If you have a separate rmi package that would be a better choice IMO.
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
Jacques<br />*******<br />MCP, SCJP, SCJD, SCWCD
Don't get me started about those stupid light bulbs. |