aspose file tools*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes RMI local?, remote? urgh 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 "RMI local?, remote? urgh" Watch "RMI local?, remote? urgh" New topic
Author

RMI local?, remote? urgh

J Hartley
Ranch Hand

Joined: Mar 29, 2001
Posts: 52
Hi, all.
Many people have tried to help me(many thanks people), but im still unsure.
I have the client and server ( RMI )
I have a class called Data which may have to run on the client OR server, depending on user preference.
Initially i wanted to do the following "at the top of my code".......
--------------Fragment A
CommonDataInterface data
if ( user wants local mode ) {
data = LocalData(path of the file Db.db);
} else {
data = bind(the server,Remotedata);
}
data.lock etc etc
------------
Yes its easy to do if you dont mind getting the local class involved with RMI, but i want the local class to be pure and clean of RMI.
I want to know if the folling method is ok....
Use the adaptor pattern to have a pure local class and a remote class which do not share an interface so i cant do it like in code fragment A.
So i do this instead...
------fragment B
At the start of the code i just call...
Multiplex("local", Object local_or_remote_ref)
or
Multiplex("remote", Object local_or_remote_ref)
----
public class Multiplex{
LocalClass local;
RemoteRMIInterace remote;
remoteBool boolean;
///the Constrcutor sets remoteBool and gives a ref to either local or remote
public void getRecordCount(int i){
if (remote == true) return remote.getRecordCount(i)
else
return local.getRecordCount(i)
}
all public methods.....
....
.
--------

I hope you follow Its the last bit thats most important
Cheers
Joe
Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
In my humble opinion, I don't agree with the fact that the local class and the remote class should not share an interface. Why shouldn't they??? They are supposed to provide the same services, "they must have the same contract with the outside world", so why shouldn't they implement a common interface???
Besides, I believe your approach of having a class which does something like...
public void getRecordCount(int i){
if (remote == true) return remote.getRecordCount(i)
else
return local.getRecordCount(i)
}
goes completely against the concept of polymorphism. The idea is to eliminate all ifs... If both your classes have the same interface (aka contract), you shouldn't need to do this. In fact, I can see you forward the method with the exact same signature.
I believe you should probably do something like this...
// Initialization code somewhere
public CommonDataInterface database;
public void initializeLocalDatabase( String filename )
{
database = new Data( filename );
}
public void initializeRemoteDatabase( some remote rmi params ...)
{
database = find rmi instance of database...
}
From here onwards, all you have to do is call database.someMethod(), and it should work no matter which actual class you are using...
Perhaps the most anti-intuitive reason not to share an interface is that RMI needs all methods to throw a RemoteException and implement the Remote interface. Perhaps in the object-oriented software construction, the local data class shouldn't implement the remote interface and will never throw RemoteExceptions, but you shouldn't be hurt by doing it.
public interface Database extends java.rmi.Remote
{
public mymethod() throws RemoteException, DatabaseException;
}
I also disagree with some people who say that you should wrap the RemoteExceptions in an "adapter" class that rethrows them as other class exceptions, or handles them accordingly. I believe that the code where you call these methods should be aware that they "might" belong to a remote object, and hence, that something wrong in the network might happen. If it happens, catch the exception and display a dialog. Don't worry, it will never happen in local mode...
Hope I didn't hurt anybody's feelings with my ideas, and perhaps I could even help somebody...
Benjam�n
Paul Anilprem
Enthuware Software Support
Ranch Hand

Joined: Sep 23, 2000
Posts: 3299
    
    7
Benjam�n, Most of the stuff that you said is correct except the exception handling part. If you expose RMI's RemoteException to the code that uses the data class(wrapped or otherwise), the user code will need to handle RemoteException explicitly. Now, consider this:

DataWrapper dw = XXXFactory.getData(...); //returns either a wrapper to local data or RMI based remote data.
When you call methods on dw, you'll have to use specific try/catch :
try
{
...
dw.modify(...);
...
}
catch(RMIException re) //For handling RMI case
{
...
}
catch(DatabaseException de) //For handling local case
{
...
}
Of course, you can catch Exception but then that defeats the whole purpose of exposing specific exceptions.
Now, suppose you develop another DataWrapper based on Socket, SOAP or CORBA or some other remoting mechanism. And you want your factory to return appropriate Wrapper depending on the parameters ie. the factory may return SOAP impl or Socket Impl or CORBA impl and all these guys throw different exceptions! You will realize that you have to modify your user class to handle different exceptions which is a very bad thing.
The user class does not have to know the remoting mecanism of the Data object. It's the job of the Wrapper object to shield the user code from implementation details of the actual data object and so the wrapper interface should throw only one kind of exceptions to the user. If the remoting mecanism changes, the corresponding wrapper should handle the specific exceptions. It should then extract out the actual message and throw the standard exception that the user class knows about.
HTH,
Paul.

------------------
Get Certified, Guaranteed!
(Now Revised for the new Pattern)
www.enthuware.com/jqplus

Your guide to SCJD exam!
www.enthuware.com/jdevplus
Try out the world's only WebCompiler!
www.jdiscuss.com


Enthuware - Best Mock Exams and Questions for Oracle/Sun Java Certifications
Quality Guaranteed - Pass or Full Refund!
Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
Paul,
Thanks for your reply. I believe you are right in what you say. When I "said/meant" for the client code to be aware of Remote Exceptions, my intention was to make clear that the client should know if the exception was really a network/orb protocol exception, rather than some other type of exception, and hence take some appropiate action (message dialog, disconnection). But your point is excellent... Perhaps a better approach would be a Decorator like:
public class RemoteDataWrapper implements DataInterface
{
RemoteDataInterface data;

public RemoteDataWrapper( RemoteDataInterface data )
{
this.data = data;
}
public void someMethod() throws DatabaseException
{
try
{
}
catch( RemoteException e )
{
handleRemoteException( e );
}
}
private void handleRemoteException( RemoteException e )
{
JFrame parentFrame = ... //get parent frame somehow
JOptionPane.showMessageDialog( parentFrame, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE );

disconnect(); // disconnect from remote server
}
}
Perhaps this looks better....
Benjam�n
Paul Anilprem
Enthuware Software Support
Ranch Hand

Joined: Sep 23, 2000
Posts: 3299
    
    7
Again, by putting the following in the wrapper
------------------
JFrame parentFrame = ... //get parent frame somehow
JOptionPane.showMessageDialog( parentFrame, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE );
------------------
you are tightly coupling your view with the controller. A big NO NO.
The point is, the wrapper doesn't know what kind of component would be using it. So how can it make a decision of getting the frame and displaying the message?
May be there is a servlet that is using your RMI Wrapper, how will it pop up this kind of message?
HTH,
Paul.
------------------
Get Certified, Guaranteed!
(Now Revised for the new Pattern)
www.enthuware.com/jqplus

Your guide to SCJD exam!
www.enthuware.com/jdevplus
Try out the world's only WebCompiler!
www.jdiscuss.com
Anonymous
Ranch Hand

Joined: Nov 22, 2008
Posts: 18944
Paul,
I'm a bit confused now... If I'm going to use a wrapper to handle the remote exceptions thrown by RMI Remote Objects, how am I supposed to communicate to my client that something in the network failed.... More specifically, where in my code will I let know the user that it has failed???
If I catch the exceptions in the wrapper, what do I do with them??? Rethrow them as some other exception??? Ignore them???
I certainly don't understand your suggestions...
Please, comment on this...
Benjam�n
Paul Anilprem
Enthuware Software Support
Ranch Hand

Joined: Sep 23, 2000
Posts: 3299
    
    7
Catch them in the wrapper, extract the message and rethrow a new exception (which would be in the throws clause of the method given in the interface/abstract class that this wrapper is impelementing/extending) containing the message.
This way the client code which is using the wrapper/adapter does not have to care whether it is a local database or a remote one. It doesn't even have to worry about the technology of the remoting mechanism used by the remote db adapter. All it gets is the result or standard exception. The exception would contain approriate message which can be either popped up as a dialog or can be put into a jsp or whaterever is the mode of delivery.
HTH,
Paul.
------------------
Get Certified, Guaranteed!
(Now Revised for the new Pattern)
www.enthuware.com/jqplus

Your guide to SCJD exam!
www.enthuware.com/jdevplus
Try out the world's only WebCompiler!
www.jdiscuss.com
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: RMI local?, remote? urgh