Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

NX: Connection problems

 
Nicholas Cheung
Ranch Hand
Posts: 4982
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am now working in the Remote Connection part.
For the local connection, there is a class DatabaseConnector which try to get the connection.
For local one, it simply do this:

The interface Services defines all functions provided to the client, and ServicesImpl provides the implementation of the method.
But when I bind this class to the RMI server, the complier complaints that "NO REMOTE EXCEPTION DEFINED".
It is obvious that I can modify the Services to allow the functions to throw RemoteException, but I dont think this is a good idea becos for local connection, it is impossible for the server to throw this exception.
Only remote connection will deal with this exception.
Could anyone advice me how should I deal with this issue?
Thanks a lot.
Nick
[ November 24, 2003: Message edited by: Nicholas Cheung ]
 
Andrew Monkhouse
author and jackaroo
Marshal Commander
Pie
Posts: 12014
220
C++ Firefox Browser IntelliJ IDE Java Mac Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Nicholas,
Your classes do not have to throw the RemoteException as long as they declare that they can throw it.
But if you don't like such an RMI specific exception in your interface, you could follow Max's example of declaring in the interface that each method throws the parent of the RMI Exceptions: IOException. This still leaves you declaring that each method throws an exception that it may never actually throw, but it is a little cleaner.
Another alternative is to have a Factory on the client side which hides the connection type from the remainder of the client code. The factory can produce a class which implements a common interface on the client side (it could even produce a class which implements Services), but the class that handles the RMI connection could work internally with a totally different interface which does throw the RMI Exceptions.
Regards, Andrew
 
Nicholas Cheung
Ranch Hand
Posts: 4982
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Andrew for answering.

Your classes do not have to throw the RemoteException as long as they declare that they can throw it.

Yes. For local connection, the server won't throw the RemoteException.
However, consider my current design:
In the GUI part:
[Client] --- [Main Window] --- [GUI Controller] --- [Connector]
The Connector tries to get the server object like this:

Since my interface Services looks like this:

The complier complaints the read() do not throw RemoteException.
Since I wish to use the same interface Service for both type of connection (for simplcity and more transparent to client), how should I do?


But if you don't like such an RMI specific exception in your interface, you could follow Max's example of declaring in the interface that each method throws the parent of the RMI Exceptions: IOException. This still leaves you declaring that each method throws an exception that it may never actually throw, but it is a little cleaner.

I think Max's example is a bit different, becos he can throw IOException in "Data" class, but we cannot. As an alternative, I have wrapped it into DatabaseException (extends RuntimeException), and throw it out.
If I try to define IOException, then it seems quite strange.
In addition, if I do so, I can take the simplest way:

to make the thing work.
Since I dont think it is a good way for design, I am still suffering here.
At first, I have a very stupid idea, thinking that I have an empty interface Services, and 2 other interfaces LocalServices and RemoteServices extends it, both have the same definition except the exception thrown.
But then, when I put it into my code, it cant compile complaint that the interface Services does not have a function call read(int recNo)

Another alternative is to have a Factory on the client side which hides the connection type from the remainder of the client code. The factory can produce a class which implements a common interface on the client side (it could even produce a class which implements Services), but the class that handles the RMI connection could work internally with a totally different interface which does throw the RMI Exceptions.

I have looked for this approach, but still in the progress of reading and searching.
 
Andrew Monkhouse
author and jackaroo
Marshal Commander
Pie
Posts: 12014
220
C++ Firefox Browser IntelliJ IDE Java Mac Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Nicholas,

Originally posted by Andrew Monkhouse:
Your classes do not have to throw the RemoteException as long as they declare that they can throw it.
Originally posted by Nicholas Cheung:
Yes. For local connection, the server won't throw the RemoteException.
However, consider my current design:
In the GUI part:
[Client] --- [Main Window] --- [GUI Controller] --- [Connector]
The Connector tries to get the server object like this:

Since my interface Services looks like this:

The complier complaints the read() do not throw RemoteException.
Since I wish to use the same interface Service for both type of connection (for simplcity and more transparent to client), how should I do?

I think you missed my point there. If your interface looked like this:

Or like this:

Then you won't have a problem with the RMI Compiler complaining.
Note that ServicesImpl does not have to throw RemoteException or IOException, as long as it declares that it can throw them.
I do agree that this is not a very nice way of handling it though: you have an unused throws clause

Originally posted by Andrew Monkhouse:
Another alternative is to have a Factory on the client side which hides the connection type from the remainder of the client code. The factory can produce a class which implements a common interface on the client side (it could even produce a class which implements Services), but the class that handles the RMI connection could work internally with a totally different interface which does throw the RMI Exceptions.
Originally posted by Nicholas Cheung:
I have looked for this approach, but still in the progress of reading and searching.

Just to give you an idea of what I am talking about with this one:

Now all that was written off the top of my head, so it may not even compile. It is just designed to give you something to think about.
Regards, Andrew
 
Nicholas Cheung
Ranch Hand
Posts: 4982
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Andrew. I get your idea from the example.
We can try catching the remote exception, and wrap it into our own exception, and thus, the "root" interface in fact do not need to declare such exception.
In addition, should I do this?

So, my root interface is in fact should be different to the Remote interface? As from the suggested approach, interface implemented by RemoteServer should throw RemoteException. Thus, the wrapping should be done in the Adapter?
Am I correct?
Thanks.
Nick
[Andrew: Added [code] tags around the diagram]
[ November 27, 2003: Message edited by: Andrew Monkhouse ]
 
Andrew Monkhouse
author and jackaroo
Marshal Commander
Pie
Posts: 12014
220
C++ Firefox Browser IntelliJ IDE Java Mac Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Nick,
Using an adapter is certainly another valid way of doing it, however I don't think it is as clean ... I will get to that shortly.
Just to be certain you understand it, my example is:

Where both RemoteDoSomething and LocalDoSomething implement a common interface (DoSomething) which does not throw RemoteException. If RemoteDoSomething catches a RemoteException, it wraps it in an exception that is thrown by the DoSomething interface.
The advantage of having the factory is that you can add as many different connection methodologies as you like, without doing anything special about the connection exceptions that might be thrown. They are all handled (and possibly wrapped) inside the equivalant of the NetworkClient class.
Now compare that to your suggestion of having an Adapter class. This can work equally well for something as simple as this assignment. Your code could then look something like:

As you can see, this means that every method in the Adapter will have to have either a case statement or an if...else statement for each way that you can connect. And each method will have to catch every type of exception that can be thrown from that particular way to connect.
Having it as a factory instead means that it is the only the class that is built by the factory for a particular connection type that has to catch the exceptions for that particular connection type, and all the code within that class is specific for that particular connection type: no case statements or if...else statements.
Regards, Andrew
[ November 27, 2003: Message edited by: Andrew Monkhouse ]
 
Nicholas Cheung
Ranch Hand
Posts: 4982
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Andrew.
I have a clear picture now.
Many thanks
 
Mellon Sun
Ranch Hand
Posts: 126
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I read,and I understand it.
You are all very nice. Thank you.
 
Nicholas Cheung
Ranch Hand
Posts: 4982
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Andrew,
After reconsidering all ideas collected, I finally come up this design for the implementation.

Any enhancements needed?
Any comments are welcome.
I will start the re-enginnering process tomo
Many thanks to all.
Nick.
[ November 28, 2003: Message edited by: Nicholas Cheung ]
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic