• 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
  • Tim Cooke
  • Ron McLeod
  • paul wheaton
  • Jeanne Boyarsky
Sheriffs:
  • Paul Clapham
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
  • Himai Minh
Bartenders:

RMI registry service timeout

 
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
First, let me console anyone who may think I haven't put enough effort in to resolving my problem before posting here by saying I have searched through both this forum and many, many, many web sites without much joy. I have encountered the term "garbage collection" but I can't figure out whether this applies and what to do if it does. I hope that someone can give me the answer and I don't mind if you also scold me brutally for not finding it at "extremely obvious location X" because at this stage the relief will far exceed the humiliation.

Q1) I am successfully running an RMI server and client over a network using Netbeans, on Ubuntu PCs (successfully after discovering by accident that the package names have to match!!!). My problem is that the server program terminates after exactly 60 minutes and 1 second. I then have to manually re-run the server programme. This is no good because I am trying to make a file server and I want the server to server object stubs forever without fail. Specifically, how do I stop it timing out?

Here's the business end of the server program:
public static void main(String args[]) {
try {
System.setProperty("java.rmi.server.hostname", HOST);
Server obj = new Server();
Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);

Registry registry = LocateRegistry.createRegistry(PORT);
registry.bind("Bronx", stub);

System.out.println("Server ready");
} catch (Exception e) {
System.out.println("Server exception: " + e.toString());
e.printStackTrace();
}
}

Q2) I am fairly experienced with Java but new to networking and web apps. Is RMI the recommended, mainstream
technique for transferring data from a server to a remote Java program and/or Webpage with applet? Or is
RMI not the way most people would do this?

Many thanks in advance.
 
Brian Milthorp
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have made some progress. The issue appears to involve creating the registry from within the Java program. As an alternative I created the registry from a command line as an independent process, prior to running the Java server program, and nothing timed out all night. It didn't work, at first, but once I got it working it has remained operational over night. I still don't understand why there is this difference.

For the benefit of other greenhorns, here are a few "must do"s based on my experience that were absent or unclear from all the RMI web sites and Sun tutorials I have read:

1) When RMI doesn't work the error messages you get are not clear at all. At least not to me. So tracking problems down is a real pain. So don't beat yourself up too much.

2) The client program and the server program must both contain an identical interface class, including the package they are in. For reasons that I do not understand if the package is different the registry won't realise that it is the same interface definition even though the class definition is identical. This mistake results in an unmarshal error/class not found exception.

3) My registry needs to be told what host it is on. Which is not intuitive. The way this is done is to set a Java VM variable called "java.rmi.server.hostname". This can be done from a command line or from within the program. It can be set after you run the registry. I did this from within my program as part of the server program main method. This is done using code like 'System.setProperty("java.rmi.server.hostname", "192.168.1.2");' This mistake results in a registry not found on host 127.0.1.1 or similar.

4) You don't need to use an RMISecurityManager at all to make this system work. It is a good precaution, but everything works fine without it. This surprised me having read plenty of stuff that always prescribed one and then overcame the resultant issues of access denial by suggesting finding some/all (who knows?) of your java.policy files and adding instructions in them to allow everything to talk to everything else, everywhere. I wasted a lot of time on this one!

5) The registry may not know the path to your objects which you wish to export stubs for to your client. Why not? Why doesn't Netbeans or the Java compiler deal with this for you? I know not. The documentation talks about setting your classpath to include your java classes. Let me translate this for you. It actually means setting the java.rmi.server.codebase variable to the parent directory where your server-side programs *.class files are located. In Netbeans, this turns out to be within the build directory. In my case it is the folder "build/web/WEB-INF/classes/" and the trailing "/" is required, I believe. I wasted a lot of time on this one too! I can't recall the result of this mistake but it was probably another unmarshalling error or class not found. BTW I have no idea what "marshalling" means either.

6) There is a restriction on what variable types you can transfer over RMI. The variables must be "serializable". You can tell whether a variable/class is serializable by looking at the class definition and checking it implements the "serializable interface". String does. Integer does. Byte does. That is as far as I have got so far. So you can transfer Strings between client and server and byte[] and int[] but you cannot pass a BufferedImage, for example.

7) Having changed to using an already-running rmi registry (started from my Ubuntu command line using 'rmiregistry &') I had to change from "bind" to "rebind" in the server code to avoid an error the second time I ran the program. Rebind seems to work whether the stub has been registered already or not.

8) You don't have to use the default port 1099. When you run the registry, having killed any existing instantiations, add the port number: 'rmiregistry 12345 &'. This is the linux registry command; it is different on Windows. Also change the port references in your client and server side programs.

Hope this helps someone. If I discover any more essential secrets I'll post them here.
Brian

Here is my latest main class from my server-side program, 'class Server() implements Hello':

public static void main(String args[]) {
try {
System.setProperty("java.rmi.server.hostname", "10.8.0.1");
System.setProperty("java.rmi.server.codebase","file:/srv/applications/RemoteInterface/build/web/WEB-INF/classes/");
Server obj = new Server();
Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);

Registry registry = LocateRegistry.getRegistry("10.8.0.1", 1099);
registry.rebind("Bronx", stub);

System.out.println("Server ready");
} catch (Exception e) {
System.out.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
 
reply
    Bookmark Topic Watch Topic
  • New Topic