1

Oracle says that registry is

a bootstrap naming service that is used by RMI servers on the same host to bind remote objects to names

Now, I have such a server that uses rmiregistry for providing JNDI.

public class ObjectProvider {
    public static void main(String[] args) {
        System.setProperty("java.rmi.server.codebase", "file:/absolute/path/to/jar/where/person/class/is/my.jar");
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
        Context context = new InitialContext(env);
        context.bind("jordan", new Person("Michael Jordan"));
        Person p = (Person) context.lookup("jordan");
        System.out.println("jordan = " + p.getName());
    }
}

And Person class:

public class Person implements Remote, Serializable {
    String name;
    public Person(String name) { this.name = name; }
    public String getName() { return name; }
}

And rmiregistryis started as rmiregistry &. Yet, when I run the code it complains about not being able to unmarshall arguments when performing bind because the class Person cannot be found.

I understand that rmiregistry does not find the class file but I don't understand why. Is this the right way to tell it where it can find the classes to be bound?

gicig
  • 334
  • 3
  • 14
  • It's correct if the codebase URL is correct, but a `file:` codebase URL will only work if the clue this running in the same host, which makes RMI itself rather pointless. Also `Person` is not yet an RMI server, as it isn't an exported remote object. Are you sure you need RMI at all? – user207421 Aug 26 '16 at 17:49
  • Well, this is not a real project of mine, but rather a toy example for the purpose of getting familiar with JNDI. And RMI as the technology supporting it. My idea is to have `ObjectProvider` as a provider of objects (residing on one VM). Subsequently, I want to make `ObjectConsumer` too (residing on another VM), which will lookup the provided objects. You are right, `Person` is not an RMI server. I want to provide its instances as objects that can be looked up through JNDI. – gicig Aug 26 '16 at 18:08
  • Theoretically, `ObjectConsumer` is an `RMI` server, since it provides objects over `RMI`, but through `JNDI` as an interface. – gicig Aug 26 '16 at 18:13
  • The fact that you're using JNDI isn't relevant. It's just a layer over the `LocateRegistry` API. It doesn't interfere with codebase workings. NB Typo in my previous comment: 'clue this' should read 'client is'. I would try it with a proper HTTP codebase URL. Also your `file:/` URL isn't correct: there should be three slashes, not one, at the beginning. – user207421 Aug 27 '16 at 00:13
  • You've mentioned an `ObjectConsumer` remote object in comments, but it doesn't appear in your code. When and where are you constructing it, and at what point are you setting the codebase property in relation to that? And how do clients get hold of an `ObjectConsumer` if not via the Registry? – user207421 Aug 27 '16 at 13:48
  • I have uploaded all the code to [github](https://github.com/akaRoga/jndi-exercise) as a maven project. You can see all the classes there (3 in total). – gicig Aug 28 '16 at 01:04

1 Answers1

0

Though I cannot spot the problem with your program (I've reproduced it and got the same error), I can suggest you to set an explicit CLASSPATH environment variable in the same process before starting rmiregistry. This classpath must be the same as in the RMI server process. Example:

set CLASSPATH=my_class_directory:my_jar1:my_jar2...
rmiregistry &

I admit this is not a good practice according to Oracle documentation, which tells to drop off the CLASSPATH from rmiregistry. But, since you are getting the code from the localhost, it is better than not getting it working.

Little Santi
  • 8,563
  • 2
  • 18
  • 46
  • It works with this solution. What is then codebase used for? – gicig Aug 26 '16 at 23:02
  • **What** old problem? The Regisrtry works with the codebase just like any other RMI system. It can't help but work, as it is jjust another RMI server. There is plenty of working code to prove it. – user207421 Aug 27 '16 at 00:09
  • @EJP You are right: There should be no problem, but I still find it as a valid solution in this case (I've edited my post). – Little Santi Aug 27 '16 at 08:48
  • It isn't a valid solution because it doesn't solve the problem. If the codebase URL is wrong, letting the Registry not use it doesn't solve the same problem for the client. When you've solved it for either, you've solved it for both. The problem here appears to be an invalid codebase URL. Fix that and you fix it all. – user207421 Aug 27 '16 at 10:04
  • 1
    Well, the answer solves my problem in sense that I can execute my toy example. However, I want to do it properly, i.e., with the `java.rmi.server.codebase` option in use. The [Oracle example](https://docs.oracle.com/javase/tutorial/rmi/running.html) tells that the VM option `java.rmi.server.codebase` should be passed when starting the RMI server, in my case it is `ObjectProvider`. Still, the problem is the same. The class can not be found. And yes, I have specified the URL with three slashes (file:///absolute/path/to/jar/my.jar). – gicig Aug 27 '16 at 12:51
  • 1
    @EJP "If the codebase URL is wrong". Is it? I've tested the experiment of the OP with a similar URL (even with 3 slashes as you say - which is not necessary), with an absolute path, with an HTTP URL... and the error persists. What's wrong with this experiment? – Little Santi Aug 27 '16 at 12:53
  • Whatever is wrong, just throwing out the codebase feature isn't the correct solution. The feature does work. As I said in comments above, there is no point in using a `file:` URL. I cannot possibly tell you what is wrong with your experiment without knowing anything about it beyond these vague statements. – user207421 Aug 27 '16 at 13:41