jQuery in Action, 2nd edition*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes RMI method invocation return value Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "RMI method invocation return value" Watch "RMI method invocation return value" New topic
Author

RMI method invocation return value

Radi Hadzhiyski
Ranch Hand

Joined: Jun 30, 2009
Posts: 47
Hello there,

i am testing my rmi functionality and have the following problem:

i start my server:

my client connects:

then when i invoke some void method like bookRoom:

there is no problem, but when i should receive value:

my list stays null??? so i become later a NullPointerException, if i try to pick up the result.
(the method public List<Room> searchRoom(...) returns a proper list, i've checked it.)
The Room object implements Serializable

What could be the problem?
If someone wants, i can post here the complete exception trace.

Thanks.


SCJP 1.6 (91%), SCJD
Roberto Perillo
Bartender

Joined: Dec 28, 2007
Posts: 2258
    
    3

Howdy, Radi!

Champion, it's kindda weird, because if you are able to invoke a method that returns void without any problem, then you should also be able to invoke a method that returns something. By the way, you may consider always verifying if the arguments that you receive in your business methods are null; if so, you can throw an IllegalArgumentException. For instance, if these services are to be used out of the scope of this application, then they're already prepared. This makes your code stronger and more reusable!
Now, back to your problem... could you please post the stack trace for us to have an idea of what's going on? Meanwhile, I'll try to think about what could be wrong here.


Cheers, Bob "John Lennon" Perillo
SCJP, SCWCD, SCJD, SCBCD - Daileon: A Tool for Enabling Domain Annotations
Radi Hadzhiyski
Ranch Hand

Joined: Jun 30, 2009
Posts: 47


Wow i found something...but what it is, i dont know
my business method finds the Room objects and puts them into the list
(i've checked that, the list i not empty when i invoke the method local)
in my gui i have something like result = remoteObj.searchRoom(...)
now i see that result contains my Room objects, but when i use roomObj.getHotelName a become
the Exception, so my Room object is empty, but actually thats my search method:

Roberto Perillo
Bartender

Joined: Dec 28, 2007
Posts: 2258
    
    3

So it looks like there's something wrong with your search algorithm, but the server is retrieving data!
Now, your searchRooms() method is a business method, right? You may consider throwing only a business exception and not throwing RemoteException, Because this would imply that the remote server is being used, and whoever is using it would know that a remote server is being used. If you use only your business interface and not include infrastructure details (such as RemoteException), you could promote more abstraction and more reusability.
Radi Hadzhiyski
Ranch Hand

Joined: Jun 30, 2009
Posts: 47

Hi

i found the problem

it was because i have Logger that is transient, so i need to override the readObject by de-serialization.
So this problem is gone now, but:

about my BusinessLayer:

ich have BusinessLaye that is implemented by BusinessLayerImpl
and when i start networked client i have BusinessLayer obj = Naming.lookup....
and when i start the standalone mode i have BusinessLayer obj = new BusinessLayerImpl();

the other way is to have two interfaces + 2 Impl classes that do the same thing,
except the remote one extends UniCast... and the local doesn't extends UniCast.. and the
interface of the local doesn't extends Remote (so the methods of the local interface dont have to throw RemoteException).

But then i will have 2 identical interface+class relation, except the RemoteExceptions. Is that better?
Roberto Perillo
Bartender

Joined: Dec 28, 2007
Posts: 2258
    
    3

Howdy, Radi!

But then i will have 2 identical interface+class relation, except the RemoteExceptions. Is that better?


Well, not really

It would be better to have only one business interface, and have two implementations of it. I'd just add some mechanism to retrieve the implementation to be used by the client of this interface (i.e. a factory), so that the client does not know where the data is being retrieved, and then instead of saying "BusinessLayer obj = Naming.lookup...", you'd get the implementation from this factory, because if you are saying "Naming.lookup", then the client of this interface knows that the data is coming from a remote server. If you could say "BusinessLayer obj = BusinessLayerFactory.getInstance()", then you could promote more abstraction and more reusability. This way, if there's a third implementation of it in the future, and you decide to use it, then the code of the client of the BusinessLayer interface does not have to be changed.
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5139
    
  12

Hi Radi,

My solution had 1 BusinnessLayer-interface and 2 implementations, 1 for local use and 1 for network use.

Sample code looks like this:


in your client you will be able to do something like this:

I believe such an approach keeps your code easy and simple.

Kind regards,
Roel

[edit] oops, Roberto was a tiny bit faster
[edit] added required BusinessServiceRemote-interface (remark Radi)


SCJA, SCJP (1.4 | 5.0 | 6.0), SCJD
http://www.javaroe.be/
Radi Hadzhiyski
Ranch Hand

Joined: Jun 30, 2009
Posts: 47
Thanks guys,

is it Ok, when i have the same like you Roel, but with one more interface like this:

Roberto Perillo
Bartender

Joined: Dec 28, 2007
Posts: 2258
    
    3

Roel De Nijs wrote:[edit] oops, Roberto was a tiny bit faster


But that's ok, because... well, you know what they say about great minds

Just one observation on Roel's code:



Hum... the business interface could throw only its own exceptions... having a method throwing RemoteException implies that the data is being retrieved from a remote server. One thing that could be done here is:



This way, the client of the BusinessService interface does not know where the data is being retrieved from! You can also create an hierarchy of exceptions, each exception for a particular problem.
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5139
    
  12

Hi Radi,

I was wrong I had indeed (like you showed) 2 interfaces, because the remote interface has to extend Remote, otherwise you will have a ClassCastException. I tried all the different possibilities when i was experimenting with the RMI solution of my assignment. The thread can be found here. So you definitively need 2 interfaces (BusinessLayer and RemoteBusinessLayer). I will update my previous post too, so other javaranchers won't be mislead).

@Roberto: about your observation on my code. If you have a thick client, you can have a business layer at the client, wrapping the remote exceptions in the business exception (like you demonstrated with your code snippet). If you (like I did) are making a thin client, your business layer will be the server and so you are required to have RemoteException in the throws-clause of each method, otherwise you will have trouble running your server: RemoteException("remote object implements illegal remote interface")

Kind regards,
Roel
Johnny Barbosa
Greenhorn

Joined: Sep 29, 2009
Posts: 26
Roel De Nijs wrote:Hi Radi,
My solution had 1 BusinnessLayer-interface and 2 implementations, 1 for local use and 1 for network use.
Sample code looks like this:


I'm thinking about this approach!
However, I see a problem! The client must to catch a exception that never will be thrown and never would do sense to it.

So, I think that would be better way following :

So, ww can do:

and...


What do you think, about it??


Cheers,
Johnny Barbosa
SCJA, SCJP, SCWCD, SCJD(Story | Relato), SCBCD (coming soon)
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5139
    
  12

Hi Johnny,

Did you try if your provided solution compiles? I don't think so, because my compiler gives me following error

And I don't have to use a compiler, because I know that wasn't a valid method override, and rules about valid method overrides and overloads is one of the key points of the SCJP-exam (in my opinion).

And in my code I have following lines (like in the example code above):

So you don't know which service will be retrieved. Because it is determined at runtime, depending on the program argument is used: "alone" or none argument (= "networked"). So my client code for networked and stand-alone mode is exactly the same, not seperate like you suggested.

Kind regards,
Roel
Johnny Barbosa
Greenhorn

Joined: Sep 29, 2009
Posts: 26
Roel De Nijs wrote:Did you try if your provided solution compiles?


Sorry, I forget to edit the code correctly! Sorry, again! I edit and did the correction.
Yes, I understood your point of view. But, I think that are clients totally differents (alone and connected), which would must to keep controls different.
If you catch RemoteExceptions in code that never would need them, you code would be semantically incorrect.

However, in each approach there is a cost to pay.
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5139
    
  12

Hi Johnny,

Agreed that if the 2 clients (network and stand-alone) are different another approach would be more appropriate, but in this assignment they are completely the same. I speak of course for my provided solution, but depending on the instructions the only difference would be the configuration settings you have to enter.

And there is yet another approach possible:

Your local implementation will implement BusinessServiceLocal and the network implementation will implement BusinessServiceRemote, I think that 's quiet obvious



Kind regards,
Roel
Leah Knowles
Greenhorn

Joined: Sep 25, 2009
Posts: 8
I am working on RMI now and having this familiar problem with how to handle RemoteException. As it is not thrown the supplied Sun interface DBMain I cannot throw it in my RMI Data Implementation class.

I found this old thread and saw Roel's and others suggestions to have 2 interfaces BusinessService and BusinessServiceRemote each of which are implemented by differemt classes one for local and one for remote.

What I cant wrap my head around is exactly where these Business services fit in with the Sun interface DBMain and required implementation Data.java? I currently have Data class implementing my own interface ExtendedDbMain which extends DBMain and my Connector class returns a data object.

If Roel or someone with similar solution or implementation has some advice to point me in the right direction on this would be appreciated

Leah
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5139
    
  12

Hi Leah,

I'm kind of living on this forum, so here's the answer. It's pretty easy. This is where the BusinessService (could) come into play:

GUI --> BusinessService --> Data

So the Gui invokes the business service methods. And the business service invokes the methods from the sun interface you have to implement (and thus has a reference to your Data class).

Hope it helps.
Kind regards,
Roel
Leah Knowles
Greenhorn

Joined: Sep 25, 2009
Posts: 8
Hi Roel

Yes noticed you are here a lot which is great for us "learners".

I thinking I'm slowly getting it. So would it be accurate to say that the Business Service implementation is referencing Data class via composition?

Also are you using some connector class to pass a reference of your business Service Implementation back to the GUI? Sorry if asking you divulge too much detail about your implementation.

Leah
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5139
    
  12

Leah Knowles wrote:Yes noticed you are here a lot which is great for us "learners".

Just 6-7 months ago, I was also a "learner"

Leah Knowles wrote:So would it be accurate to say that the Business Service implementation is referencing Data class via composition?



Leah Knowles wrote:Also are you using some connector class to pass a reference of your business Service Implementation back to the GUI?

To get a reference to my business service implementation I took the same approach as in Andrew's book, so yes indeed I used 2 connector classes.

Kind regards,
Roel
Roberto Perillo
Bartender

Joined: Dec 28, 2007
Posts: 2258
    
    3

I'm still a learner. When I saw Philip Wadler's workshop in this year's ECOOP, I noticed that there's still a very long road ahead...
 
 
subject: RMI method invocation return value
 
Similar Threads
error: ObjID already in use
RMI UnicastRemoteObject
Weird RMI Error: Incompatible types for storing into array of arrays or objects...
My results, my Thanks and my Warning
java.net Socket port number question