From: Screamin Lord Byron on
Hello,

I am learning RMI and I ran into this difficulty.

Let's say we have:

import java.rmi.*;

public interface Foo extends Remote {
public Bar constructBar(String name);
// other stuff
}

public interface Bar extends Remote {
public void mutate();
}

---------

import java.rmi.*;
import java.rmi.server.*;

public class BarImpl extends UnicastRemoteObject
implements Bar {
String name;
public BarImpl(String name) throws RemoteException {
this.name = name;
}

public void mutate() throws RemoteException {
name = "some new name";
}
}

---------

import...

public class FooImpl extends UnicastRemoteObject
implements Foo {

public FooImpl() throws RemoteException {
// some init
}

public Bar constructBar(String name) throws RemoteException {
return new BarImpl(name);
}

// other stuff

}


----------

Now I have some server and rmi initialization in the main class

----------

import...

public class Server {
public static void main(String[] args) {

// Construct Foo implementation, no problem
FooImpl myFoo = new FooImpl();

// Construct Bar Implementation
BarImpl myBar = new BarImpl(// oops, don't have the name,
// the client has it
);

// So I can bind Foo,
new InitialContext().bind("rmi:my_foo", myFoo);

// But can't bind Bar

}
}

I don't even know how many Bars there will be, and I can't just
serialize Bar and transfer a copy to the client, because I need all Bars
to be remote.

However, if I try to bind in constructBar() method of the Foo class I
get something like this on the client:

java.lang.IllegalArgumentException: illegal remote method encountered:
public abstract void Bar.mutate()

I suppose it's because there is no Bar in the RMI registry yet.

What can I do? I'm sorry if I'm asking nonsense, but how to make a stub
object for this Bar class? Am I doing it completely the wrong way?

I have no problem invoking methods of remote objects instantiated by the
server. That is to say -- if I remove this Bar business, everything else
runs as expected.

I've just started with RMI so (obviously) I don't know anything about it
yet. Can you please tell me is maybe Remote Object Activation right way
to look?

Thanks!
From: markspace on
Screamin Lord Byron wrote:
>
> I don't even know how many Bars there will be, and I can't just
> serialize Bar and transfer a copy to the client, because I need all Bars
> to be remote.

I don't know much about RMI either, although I might have some time to
give this some thought and make some test code.

Could you elaborate on the "I don't know how many Bars there will be"
part? What does that mean? Types of Bars, or different Bars with
different data but are all the same type? I think it makes a difference.

Couple of solutions occur to me, like a Proxy Pattern or a Type Object,
but I'd have to know a little more about the problem details.


From: Tom Anderson on
On Thu, 22 Jul 2010, Screamin Lord Byron wrote:

> public class FooImpl extends UnicastRemoteObject
> implements Foo {
>
> public Bar constructBar(String name) throws RemoteException {
> return new BarImpl(name);

I have a vague idea you have to say something like:

return UnicastRemoteObject.exportObject(new BarImpl(name));

here. But i could be wrong.

tom

--
The literature, especially in recent years, has come to resemble `The
Blob', growing and consuming everything in its path, and Steve McQueen
isn't going to come to our rescue. -- The Mole
From: Screamin Lord Byron on
On 07/22/2010 09:31 PM, markspace wrote:
> Screamin Lord Byron wrote:
>>
>> I don't even know how many Bars there will be, and I can't just
>> serialize Bar and transfer a copy to the client, because I need all Bars
>> to be remote.
>
> I don't know much about RMI either, although I might have some time to
> give this some thought and make some test code.
>
> Could you elaborate on the "I don't know how many Bars there will be"
> part? What does that mean? Types of Bars, or different Bars with
> different data but are all the same type? I think it makes a difference.

There will only be instances of BarImpl class, and only methods declared
in the Bar interface will be used.


> Couple of solutions occur to me, like a Proxy Pattern or a Type Object,
> but I'd have to know a little more about the problem details.

I am making a little card playing game to do some practice with Java.
The game logic is done, and now it's time to make the server which will
host the game and the client for the players. I chose RMI just to get
myself more familiar with it (although I admit it may not be the optimal
choice).

This is the game. It's quite popular in some parts of my country (not
that it really matters for this discussion :) )

http://en.wikipedia.org/wiki/Belot

What matters is that players can't just play any card they like (they
must follow suit, etc.). The Player class has the hand field which
contains 8 cards (that class is what the BarImpl represents in my example).

The dealing part is done on the server. The idea is this. At the
begining of the game, all clients (one for each player) must send the
name of the player (and possibly some ID) by invoking some construction
code (something like constructBar() in my example), and it receives a
Player remote object from the server (which already contains his cards).

When player chooses a card to play, the server must check if it's a
valid move. Client uses a chooseCard(Card c) method of the Player class
which marks the chosen card and enables the game logic on the server to
check it and proceed if it's ok (remove it from hand). What I want to do
is to call player.chooseCard(card) from the client. Of course, this
means that the client's player object must not be a mere copy of the
server's player object, but it must be a remote object.

Well, that's the idea, and also the problem. :) Of course, it would be
easier to do it without RMI with some simple quickly-made-up
communication protocol, but I'm just curios is it possible to make it
work as I imagined with RMI.

The issues like how to notify all clients that the card is played and
such are not important right now. I have some idea on how to handle that.

And yes. Thank you for reading all this. :)

From: Screamin Lord Byron on
On 07/22/2010 11:54 PM, Tom Anderson wrote:
> On Thu, 22 Jul 2010, Screamin Lord Byron wrote:
>
>> public class FooImpl extends UnicastRemoteObject
>> implements Foo {
>>
>> public Bar constructBar(String name) throws RemoteException {
>> return new BarImpl(name);
>
> I have a vague idea you have to say something like:
>
> return UnicastRemoteObject.exportObject(new BarImpl(name));
>
> here. But i could be wrong.

Thanks. I'll give it a shot, although I'm not sure how to tell the
client it's a remote object.