• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Tim Cooke
  • Devaka Cooray
Sheriffs:
  • Liutauras Vilda
  • paul wheaton
  • Rob Spoor
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Piet Souris
  • Mikalai Zaikin
Bartenders:
  • Carey Brown
  • Roland Mueller

RMI from start to finish

 
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think, it's about time to figure out what RMI is! :roll: So basically we have two computers with JVMs running on both on them. (We could probably go with only one, but why use RMI in this case? So let's agree on two). RMI is a mediator for an object in one JVM to call a method on some other object that is located inside another JVM. Question: is RMI supported by JVM, or is it built totally on top of JVM, just like any class we write ourselves? In other words, could we implement RMI functionality ourselves, if we were stupid enough to reinvent the wheel?
Next question: which services does RMI provide? Sun's tutorial listed three:
* Locate remote objects (Naming.rebind(), Naming.lookup() etc. I suppose)
* Communicate with remote objects. providing stub and hiding underlying network issues? About network issues, you mentioned HTTP protocol, other sources talk about TCP/IP, do these two "hardcoded" into RMI, or it is possible to tell RMI somehow which protocol to use?
* Load class bytecodes for objects that are passed around. Question: which objects: remote objects, objects passed as arguments/returned from methods? Both?
Any other service?
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Michael Ernest:
Mmm, I'm not sure I'm answering the question you're asking, but here goes: Naming.lookup() is going to return a Remote reference. We need to cast that back to the appropriate interface to get the behavior we started out wanting, which requires a compile-time knowledge of the interface. I don't believe Reflection can get us around that.


Ok. Am I right that what Naming.lookup() method returns is a stub? I looked at what the stub has and you know what? It itself uses Reflection to call remote object methods. Are there any fundamental reasons we cannot use Reflection, besides obvious stupidity to use it twice? To formulate my question better: is it an absolute requirement to know the name of the remote interface at the compile time? Or is it merely simplicity/convenience/performance issue?
Actually I was reading today in "Component Development for the Java Platform" that reflection is a way a client can deal with remote objects without stubs. All it needs is an address and the name of remove interface. The book also told something about generic stubs in jdk.1.2. but frankly, I did not understand this part. As soon as they will send me this book for review I'll post exact text.
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Before we start to ask what travels where at run-time, can we check what we need to have at compile time?
Also, I caught myself that I confuse my responsibilities as a client programmer with those of server programmer. Can we separate them for educational purpose? For example, Marilyn will be responsible for server programming and Map for client. Or the other way around, I do not insist on being a client
So...
At compile time Marilyn's responsibilities are:
1. To define the remote interface (Processor in our case)
2. To write a class that implements it (Workhorse)
3. To generate a stub with rmic
4. To put all classes in some place where Web-server can access it
and my responsibilities are:
1. To get a reference to a server object via Naming.lookup() and cast it to known interface (I am still not sure if I have to know interface name, so let's call it a typical case )
2. To generate a skeleton?
3. To call appropriate methods on an object, returned by Naming.lookup().
Can I call Marilyn's services via Internet? What are typical uses for RMI? Is it used within LAN mostly?
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here are Michael's bat files translated into Windows (98, I dunno if NT uses the same syntax)
To compile Processor.java and Workhorse.java:
(assuming that your root directory is "c:\rmi")
set HOME=c:\rmi
cd %HOME%\src\mfe\services
javac -d %HOME% -classpath %HOME% Processor.java
cd %HOME%\src\mfe\servers
javac -d %HOME% -classpath %HOME% Workhorse.java

to generate a stub:
set HOME=c:\rmi
cd %HOME%\mfe\servers
rmic -d %HOME% -classpath %HOME% -keep -v1.2 mfe.servers.Workhorse

[ February 10, 2002: Message edited by: Mapraputa Is ]
 
Sheriff
Posts: 17665
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Mapraputa Is:
Ok. Am I right that what Naming.lookup() method returns is a stub? I looked at what the stub has and you know what? It itself uses Reflection to call remote object methods. Are there any fundamental reasons we cannot use Reflection, besides obvious stupidity to use it twice? To formulate my question better: is it an absolute requirement to know the name of the remote interface at the compile time? Or is it merely simplicity/convenience/performance issue?


Map, just curious since I'm not sure I understand the direction your line of questioning is taking. How exactly do you see Reflection being used (some sample code to illustrate perhaps) to take advantage of the services of the remote object?
Sure, there may be ways for you to blindly go out and lookup a registry for service providers and "browse" through what each provider has to offer. However, I don't see RMI being this type of protocol. I see it more like a way for a client to say something like "OK, I have a Contract here that guarantees a Service. I can call Directory Assistance and give them my Contract ID and they will connect me with somebody who can provide the Service to me." The Contract would be the remote interface, the Service would be the remote method, Directory Assistance would be the RMI registry and the Contract ID would be the RMI Registry URL.
What's your vision of RMI and how does Reflection fit in?
Junilu
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Map, just curious since I'm not sure I understand the direction your line of questioning is taking. How exactly do you see Reflection being used (some sample code to illustrate perhaps) to take advantage of the services of the remote object?
Must be my math background. Instead of learning only "typical cases" I was trained to examine all "extreme cases". Now I am not happy until I figure out all these "extreme" cases and uses. How Reflection can be used is the next question, perhaps there is no sensible reason to use it, now I am only concerned with theoretical possibility to use it.
Sure, there may be ways for you to blindly go out and lookup a registry for service providers and "browse" through what each provider has to offer. However, I don't see RMI being this type of protocol.
This is very important point that deserves a separate post and I am not even sure in which forum.

Originally posted by xml.com

Two old men were walking down the street one day, when the first remarked to the second, "Windy, ain't it?"
"No," the second man replied, "It's Thursday."
"Come to think of it," the first man replied, "I am too. Lets get a coke."


- from an article about Web-services. Its main point is that to make meaningful use of any kind of services, we need to have prior information about them, we cannot just "discover" them, at least not until computers will be taught to understand plain English :roll:
One way to have this kind of prior info is to "know" the name of remote interface at compile time. I do not really have anything against it, I only do not quite understand why then Naming.rebind() uses artifical "serviceName" instead of genuine remote interface name, if we will cast the returned object to it anyway? Now we need to know not only interface name, but also how it was registered. Seems redundant to me. Why yet another level of indirectness?
What's your vision of RMI and how does Reflection fit in?
I do not think I have any vision of RMI, I am only trying to build one. And the harder time I can give to Michael, the better. My idea about Reflection was partly inspired by these Michael's words: "Furthermore, a well-named lookup might do a better job of suggesting a service's uses. When we want a service, the argument goes, we usually know what capability we're looking for (like Processor), but we don't always know the exact implementation name it goes by (Workhorse). A lookup service supported by thoughtful naming can save us a LOT of tedious searching."
Michael Ernest, could you put some light: what did you mean by this?
[ February 09, 2002: Message edited by: Mapraputa Is ]
 
High Plains Drifter
Posts: 7289
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
While it is intellectually interesting to explode the subject at hand in any number of directions, I can't effectively address all those questions and stay on track. These kinds of questions are now written down however, so we can return to them at a later time. Some of those questions, I think, might answer themselves once you've seen the whole model.
However, since we haven't even written client lookup code yet, what I'm asking is whether the model I've proposed so far is clear. This is neither a proof nor an all-encompassing set of propositions, just an example. Is it ok to stick to the example for now, and come back to "why?" and "why not?" questions later?
[ February 09, 2002: Message edited by: Michael Ernest ]
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
However, since we haven't even written client lookup code yet
Since you did not give us client code, we did not have anything to play with and all we could do was to ask profound theoretical questions. Sorry for that, Michael.
what I'm asking is whether the model I've proposed so far is clear.
It looks very clear for me. Let's see what other say.
Is it ok to stick to the example for now, and come back to "why?" and "why not?" questions later?
Only if you reveal client code! :roll:
Well, Ok, but can we then ask each other? See, what a nice discussion we had with Junilu. Michael, you do not have to answer all questions, just enjoy enormous unhealthy interest your tutorial inspired
<obsolete question>Question for whoever wants to answer. I have Orion server installed on my machine. I do not have permanent Internet connection, but if you know my IP at the time I am connected, can you call my services via RMI?
</obsolete question>
Sorry for trouble, I answered myself. I typed "http:\\172.183.192.236:8000" and it worked
Michael, you are
[ February 09, 2002: Message edited by: Mapraputa Is ]
 
Sheriff
Posts: 9109
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Services (or remote services, if you wish) are just interfaces that observe two rules. One, they each extend the java.rmi.Remote interface. Two, each method in them says it throws, at a minimum, java.rmi.RemoteException.

I read somewhere that the "public" modifier is required as well. I notice you used it for the Processor interface also. Is this a remote service requirement?
 
Junilu Lacar
Sheriff
Posts: 17665
300
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
ME: what I'm asking is whether the model I've proposed so far is clear...Is it ok to stick to the example for now, and come back to "why?" and "why not?" questions later?
MI: ...but can we then ask each other? See, what a nice discussion we had ...
So that we don't sidetrack Michael from his lesson plan, I propose that we create a sidebar thread whenever we start to stray from the main topic.
Everything so far in the main thread is more or less clear to me. Let's roll, teach...
Junilu
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Marilyn deQueiroz:
I read somewhere that the "public" modifier is required as well. I notice you used it for the Processor interface also. Is this a remote service requirement?


Gee, interesting question. I first decided that you ask about method modifiers in the Processor interface, but this is, of course, trivial, they all are implicitly public whether we declare them as such or not. So you must be asking about the Processor interface itself. As Michael put his example, it *must* be public, because the Workhorse class that implements it is in another package, so if we remove "public" from the Processor interface the Workhorse class will not compile. However, I have my own example where I as a lazy woman put all classes and interfaces in the same default package. I tried to remove "public" and it seems work fine.
But even if it will compile and work, it seems antithetical to the spirit of the RMI service not to declare the remote interface as "public". In such a case only classes in the same package would be able to use it.
My version is that it's not a requirement, but a sensible thing to do.
I hope this my post is on track, and if not, it's Marilyn's fault anyway
 
Ranch Hand
Posts: 158
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Michael Ernest:

Also, I'm working on a Solaris box and darn proud of it


May I know if working on a Solaris box is something to be darn proud of ?
[ February 10, 2002: Message edited by: Sahir Shah ]
 
Michael Ernest
High Plains Drifter
Posts: 7289
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You may know it if you give yourself permission to do so.
 
Michael Ernest
High Plains Drifter
Posts: 7289
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ok, so, one last thing before we can start up our server code; we need to be able to serve our stub class to rmiregistry.
You heard me right: the act of binding a Remote object to rmiregistry isn't just registration. (And we can debate the need for String-for-service lookup translation if you like, but those who must question it aren't thinking right, and I should set you straight privately. )
When our Remote object is bound to the registry, it's actually sent (in serialized form) to the registry itself. Read back in this topic to remind yourselves that rmiregistry should have no classpath. We don't want rmiregistry to see Remote objects in its local file system; that would be bad. rmiregistry stores information about the Remote object, including where to contact it (the port number on the local machine), and of course the lookup name which, we all agreed, only the most brutish and wrong-headed of tutorial-derailers would challenge.
What the registry does not know how to do is identify the codebase of the stub object it received. It needs to verify the class file's whereabouts, and the server has to tell it where that is. The reason we shouldn't use CLASSPATH for this is simple; rmiregistry passes this same information to lookup clients. If rmiregistry happens to find the stub locally, it will ignore any codebase the server offers in favor of its own "more trusted" location. This comes in the form of a file://-based URL. So if those clients are in fact on another machine, the stub-locator scheme won't work.
Assuming rmiregistry can't see any stubs in its own classpath, it's sufficient to modify a system property the server uses to point to its class repository. This property is the codebase, or java.rmi.server.codebase to be precise. The codebase itself is an URL, and the simplest client-server protocol to use is HTTP.
That means you need an HTTP server, for our purposes a very light one. So here you go! Don't say I never gave ya nuthin'. This is the same class server offered in Sun's RMI tutorial by Ann Wolrath and Ken Arnold, by the way. It's not license-restricted other than by copyright. As a side note, if you ever wanted to write your own in-process web server, this code will get you started.
Read the instructions that come with this zip file, compile the source, then start it up so that the document root of the HTTP server is $HOME/sdocroot (or your equivalent). Use port 9999 so we're all the same. If you're really curious, use a separate session window to invoke the HTTP server, and turn the verbose option on. That way you'll see requests for the stub and the interface files get reported.
Start up rmiregistry in $HOME/tmp if you haven't already; again, make sure CLASSPATH is not set. (rmiregistry uses port 1099 by default, so that has to be available too).
Copy Workhorse_Stub.class and Processor.class into the $HOME/sdocroot. You need to show package structure through directory structure, so you should end up with:
$HOME/sdocroot/mfe/servers/Workhorse_Stub.class
$HOME/sdocroot/mfe/services/Processor.class
Alternatively, you can use a JAR file:
$HOME/sdocroot/tutorial.jar
Now you're ready to start the server, so we need to write some driver code, compile it, then fire it up:

We declared the codebase at runtime using a -D (runtime directive). There are other ways to do it, but this way makes it easy to see what's what. Our HTTP server is using port 9999; if you're using a different port, change that part.
If you're using the JAR, build it like this. From the $HOME directory:
$ jar cvf tutorial.jar mfe/servers/Workhorse_Stub.class mfe/services/Processor.class
It's important to maintain relative paths in the directory structure of the JAR; the JAR file itself acts as a "virtual root" directory for everything it contains.
The codebase must point directly to the JAR itself:
$ java -cp $HOME -Djava.rmi.server.codebase="http://localhost:9999/tutorial.jar" mfe.servers.WorkhorseDriver
If all goes well, check your web server window. If the verbose flag has been set, you should see reports that Workhorse_Stub.class was requested, then Processor.class. Congratulations! If you've gotten this far, the client part is (almost) trivial.
[ February 10, 2002: Message edited by: Michael Ernest ]
 
Ranch Hand
Posts: 445
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
ME: what I'm asking is whether the model I've proposed so far is clear...Is it ok to stick to the example for now, and come back to "why?" and "why not?" questions later?
A nice discussion. I like this tutorial. One question so far. Just curious why Michael's example takes a Runnable object as parameter? (what's the intention of that)
I am also eager to see the client side code.
 
Marilyn de Queiroz
Sheriff
Posts: 9109
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
But even if it will compile and work, it seems antithetical to the spirit of the RMI service not to declare the remote interface as "public". In such a case only classes in the same package would be able to use it.

Yes, I agree. It would seem that it should be listed as a requirement since the whole idea of RMI is to use a method, not only in another package, but on another JVM.
 
Michael Ernest
High Plains Drifter
Posts: 7289
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Doug Wang:
Just curious why Michael's example takes a Runnable object as parameter? (what's the intention of that)


I'm not ready to give away the punchline just yet, but I'll give you a hint. Both sides in this exchange already know what a Runnable is: it's a service that guarantees availability of a "behavior" called run().
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
To clarify. To run the whole thing we need:
1. Start HTTP server.
java examples.classServer.ClassFileServer 9999 %HOME%\sdocroot
2. Start RMI registry. I use bat file:
cd ..
set CLASSPATH=
rmiregistry
3. Start our driver code.
java -cp %HOME% -Djava.rmi.server.codebase="http://localhost:9999/" mfe.servers.WorkhorseDriver
The only bad thing is that I work on Windows98, not a Solaris box, so I cannot be darn proud of myself
[ February 10, 2002: Message edited by: Mapraputa Is ]
 
Marilyn de Queiroz
Sheriff
Posts: 9109
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Originally posted by Mapraputa Is:
Here are Michael's bat files translated into Windows (98, I dunno if NT uses the same syntax)


Win2K uses the same syntax so I suppose that NT does also.

to generate a stub:

set HOME=c:\rmi
cd %HOME%\src\mfe\servers


Do you mean:
cd %HOME%\mfe\servers
??
[ February 10, 2002: Message edited by: Marilyn deQueiroz ]
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes, "cd %HOME%\mfe\servers" should be better. In fact, I start rmic from %home% directory, so why do I need "cd..." thing at all?
I corrected my post anyway.
 
Marilyn de Queiroz
Sheriff
Posts: 9109
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I must be doing something wrong.

I can get everything running until I try using the jar file. It seems to jar ok.
jar cvf tutorial.jar mfe/servers/Workhorse_Stub.class mfe/services/Processor.class

gives me
added manifest
adding: mfe/servers/Workhorse_Stub.class(in = 1875) (out= 944)(deflated 49%)
adding: mfe/services/Processor.class(in = 251) (out= 174)(deflated 30%)


but
java -classpath %HOME% -Djava.rmi.server.codebase="http://localhost:9999/tutorial.jar" mfe.servers.WorkhorseDriver

gives me:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: mfe.servers.Workhorse_Stub


although tutorial.jar is in %HOME% (I can see it there and WinZip tells me that it contains mfe\servers\Workhorse_Stub.class). Do I need to move it somewhere else?
[ February 10, 2002: Message edited by: Marilyn deQueiroz ]
 
Michael Ernest
High Plains Drifter
Posts: 7289
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes! Move it over into the sdocroot directory.
 
Marilyn de Queiroz
Sheriff
Posts: 9109
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It doesn't seem able to find it there either.
 
Michael Ernest
High Plains Drifter
Posts: 7289
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Using your web browser, attempt to download the JAR manually. Go to http://<localhost>:9999/tutorial.jar. If you don't find the file through the browser, then it's a download problem.
As a precaution, add a '/' to the end of the server's codebase directive, so it's:
... -Djava.rmi.server.codebase="http://<localhost>:9999/tutorial.jar/"
...
That should do nothing at all, but hey as often as I tried that dead-end myself in the early going, the least I can do is make someone else try it.
[ February 11, 2002: Message edited by: Michael Ernest ]
 
Michael Ernest
High Plains Drifter
Posts: 7289
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Turns out the class server I pointed to can't handle JAR files. If you want to do the JAR file thing, you'll need a more robust HTTP server.
Sorry 'bout that! Thanks to Map for testing this out.
 
Marilyn de Queiroz
Sheriff
Posts: 9109
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm glad to hear that it's not just me.
I guess we can go on to the next step then.
 
Michael Ernest
High Plains Drifter
Posts: 7289
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ok, sorry, for the long delay; the JXTA invasion stole some of my attention up to this point.
We're ready to write some client stuff, and we're going to start simple by just tickling rmiregistry and making it tell us what it has to offer.

Notice here we're not actually contacting our service; we're just asking the registry (via Naming.lookup()) to tell us what it has. This is important step if you're thinking about browsing for services, of course, and its also a good way to underscore the problem of naming. (Tangent alert!)
Good names for servers matter. Why? Because, usually, we don't know their names; nor do we care. We keep the name of a service, or something I have also called a capability earlier. By this I am trying to express that we know what behavior we want. At any given moment, we want to print a document, or download a file, or bet on a cricket match. In a distributed environment, we want to discover services that support the behavior we want.
We may also want to discriminate among the available implementations, certainly. God help us if we don't exercise our power to choose at every possibile opportunity. But we don't want to be required to know the names of server classes and port numbers at compile-time in order to do that. At least I don't; we'll have to check if Map would still rather free herself of lookup services by writing her own port scanners and network sniffers to do the same thing.
More importantly, a lookup service is free to describe, at runtime, what services it knows about. We're hard-coding that information in our server objects right now, but as an argument of property given to the server at runtime, we have lots of leeway to write the code one way and describe its use in a completely -- dare I say it -- orthogonal manner.
Try this client out, and see that it returns a list of services (well, ok, service) available.
Keep a menal note: the strings return from Naming.list() can be used directly to retrieve those same services -- no modification necessary! That's nice.
Now, here's the nasty part. Quit your server program. Wait a couple seconds. Run your client list code again. Wait three minutes. Run your client. Wait just a few more minutes, then run your client again. What did you see? More importantly, what's going on?
[ February 14, 2002: Message edited by: Michael Ernest ]
 
Marilyn de Queiroz
Sheriff
Posts: 9109
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
First things first. In order to compile your code you need a couple more import statements like:

import java.rmi.RemoteException ;
import java.net.MalformedURLException ;

Also you need to catch or throw the second Exception.

Now, how do I "quit my server program"? Can I just Ctrl-C my servers DOS window or do I need to do something else?
[ February 14, 2002: Message edited by: Marilyn deQueiroz ]
 
Michael Ernest
High Plains Drifter
Posts: 7289
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Oh pick pick pick. You type-it-and-compile-it people are all the same.
The corrections are noted above. Now, you can stop your server by CTRL-C or whatever other rude means of interruption give you the greatest enjoyment. The point of this exercise is that the server is going down in an ungraceful way.
And I am waiting to hear some results/conclusions before we continue, so chop chop.
 
Marilyn de Queiroz
Sheriff
Posts: 9109
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Which server am I quitting -- the WorkhorseDriver server, the rmi server, or the web server?
 
Marilyn de Queiroz
Sheriff
Posts: 9109
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I've tried stopping the Workhorse server and the rmi server with no side effects so far.
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I stopped Workhorse server first, Web server next and nothing happened. Of course, after I stopped RMI registry a lot of useful info appeared on my screen
I guess Michael's point was to show us that after a service registered himself with RMI registry, it can go wherever he wants, even offline. It's still registered. If, however, somebody naive and maliciously misled by their so-called "teachers" will try to call such a service, they are in trouble.
[ February 14, 2002: Message edited by: Mapraputa Is ]
 
Michael Ernest
High Plains Drifter
Posts: 7289
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The exercise is to stop the WorkhorseDriver program (which "drives" the Workhorse server, see?). You could of course also stop the web server, which wouldn't change the picture. I did not intend you to kill rmiregistry, but hopefully you understand, if only in hindsight, that won't be anything to look up if you kill the lookup service.
Map has it right. You've deaded the Workhorse server, but the registry goes on happily listing that the service is available. What happens, do you think, if we make an actual call on the server object itself, which we do in our next piece of code?
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What happens, do you think, if we make an actual call on the server object itself, which we do in our next piece of code?
java.net.ConnectException: Connection refused: no further information?
 
Michael Ernest
High Plains Drifter
Posts: 7289
Netbeans IDE VI Editor
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Map, you're a beautiful human-like program, and I know you're fond of exceptions, but I wanted to know what you think would/should have happened.
But now that you know the result, was it what you expected? Why or why not?
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
We may also want to discriminate among the available implementations, certainly. God help us if we don't exercise our power to choose at every possibile opportunity. But we don't want to be required to know the names of server classes and port numbers at compile-time in order to do that. At least I don't; we'll have to check if Map would still rather free herself of lookup services by writing her own port scanners and network sniffers to do the same thing.
This is the most nasty, outrageous, indecent misinterpretation of my words that ever happened on the Ranch. Have I ever questioned necessity of lookup service per se? Each and every first-year-CS student knows that all problems in CS are solved by introducing yet another level of indirectness. There is nothing mentally challenging in it. Real challenge is to keep number of these levels as small as possible and not to mix them in your mind. That's all I asked about -
1. Not mixing up levels of indirectness:
"Do not you mix up two levels of indirectness here? "Interface - implementation" (Processor - Workhorse in your case) is an inherent virtue of Java, the OO language, itself, whereas RMI lookup service in my understanding is built on top of Java."
I can only add that in current circumstances of daily proliferating technologies, protocols and standard, it is very easy to get confused.
2. Keeping minimum of them:
"One way to have this kind of prior info is to "know" the name of remote interface at compile time. I do not really have anything against it, I only do not quite understand why then Naming.rebind() uses artifical "serviceName" instead of genuine remote interface name, if we will cast the returned object to it anyway? Now we need to know not only interface name, but also how it was registered. Seems redundant to me. Why yet another level of indirectness?"
Michael, perhaps you did not understand my question. Let me try again. We have one thing to hide - the name of implementing class and two levels of indirectness: first, we access it through interface it implements, next we access interface itself through service name, "Processor->Workhorse" in our case. What the last trick gives us? It hides implementing class? It's already hidden.

Neither of my questions met satisfactory answer. Also, you forgot to add import java.net.MalformedURLException; to your program.
Even more important, IMHO, is to understand, what each level of indirectness hides. Only the most obscurant and wicked teachers would challenge such an approach.
Michael said: "names of server classes and port numbers". Ok, but how about computer address (DNS, IP or whatever else)? Where it fits into picture? I read somewhere that rmiRegistry should be run on the same computer where service will be run. So if we have, say, two computers with services, do we have one centralized RMI register that keeps not only port numbers, but net addresses of services also, or do we have to connect to rmi registry on each computer? If this is the case, our client program would have to say not
Naming.list("rmi://localhost/");
but
Naming.list("rmi://172.145.236.00/");
or something like that.
And what about underlying protocols?
Some experts claim that "JXTA can be implemented independent of a transport protocol (ie., internet, intranet, private-network, etc"

How about RMI?
[ February 14, 2002: Message edited by: Mapraputa Is ]
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Map, you're a beautiful human-like program, and I know you're fond of exceptions, but I wanted to know what you think would/should have happened.
Why would I think, if I can check, my tiger? But thanks for "beautiful". I should admit that you are a very intelligent person and you can even be nice if you want to.
But now that you know the result, was it what you expected? Why or why not?
Apparently only two things can happen: either our service would work and return proper response or not. I would expect the latter: after we shut down the server, its service became "unavailable", and we know that Java, the platform, informs us about unavailable resources through mechanism of exceptions. Alternative variant would be for RMI registry to check whether a service is available, and if not, return null object or something. Of course, I do not quite understand what it means for service to be "available", therefore I cannot know if it's possible for RMI to check its availability. Then, it's not necessarily that the service wouldn't respond. We "shut down" our server, Ok, but cannot RMI instantiate it herself upon request? If it's run on the same machine.
All this brings us to the main question: what really happens when we run Michael's RMI example? This unfortunate case that we run client, server, and RMI on the same machine only adds to confusion.
P.S. In my native language words have gender, so I naturally think about things in male/female mode. I wonder why RMI has female identity for me...
 
Marilyn de Queiroz
Sheriff
Posts: 9109
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's interesting that although I'm starting the server with
start java -classpath %HOME% -Djava.rmi.server.codebase="http://localhost:9999/" mfe.servers.WorkhorseDriver

my output is
rmi://localhost:1099/Processor->Workhorse

rather than
rmi://localhost:9999/Processor->Workhorse
 
Marilyn de Queiroz
Sheriff
Posts: 9109
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes This stuff actually works! Map & I make a good team.
 
Marilyn de Queiroz
Sheriff
Posts: 9109
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well, it seems that the ClientList NEVER notices that the server has gone down.

So, how do we tell the rmiregistry that the server is no longer available?
[ February 16, 2002: Message edited by: Marilyn deQueiroz ]
 
Run away! Run away! Here, take this tiny ad with you:
We need your help - Coderanch server fundraiser
https://coderanch.com/wiki/782867/Coderanch-server-fundraiser
reply
    Bookmark Topic Watch Topic
  • New Topic